تصميم موقع الويب الخاص بك مع PHP و MySQL


الدرس: التعبيرات المنتظمة Regular expressions (الجزء 2/2)


الصفحة السابقة
هنا هو استمرار (ونهاية) مغامرتنا مع التعبيرات المنتظمة.

كلمة السر لهذا الفصل هي الممارسة . بصرف النظر عن بعض النقاط التي سنناقشها في البداية ، فأنت تعرف الأساسيات المتعلقة بـ regex لكنك تفتقد إلى الأكثر أهمية: التدريب!
في النصف الثاني من هذا الفصل ، سنقوم مع بعضنا ، حتى تتمكن من معرفة كيفية المتابعة حتى تتمكن في النهاية من كتابة هذه $٪ @ # $ #٪ من regex !

هناك شيء واحد لكتابة قطعة من regex كما فعلنا حتى الآن ، ولكن لإنشاء regex كاملة ، سترى أنها قصة مختلفة تماما!

قصة من الحروف الأولية metacharacters


للبدء ، وقبل المضي قدمًا ، يبدو من المهم لفت انتباهك إلى مفهوم جديد: الحروف الأولية metacharacters .

إنها ليست إهانة للمبرمج ، ولكنها كلمة تعني ببساطة "  أحرف خاصة  ". هذه شخصيات لا مثيل لها ,لها دور أو معنى معين.
في لغة PCRE (regex) ، فإن الحروف الأولية التي تحتاج إلى معرفتها هي:

# ! ^ $ ( ) [ ] { } ? + * . \ |
يجب أن نتذكرهم. بالنسبة لمعظمهم ، أنت تعرفهم بالفعل.
وبالتالي ، فإن الدولار "  $ " هورمز خاص لأنه يشير إلى نهاية السلسلة.

وبالمثل بالنسبة للكنة المحيطية ? + * ، تذكر ، الحادة ، الأقواس ، الأقواس المربعة ، الأقواس والرموز  ": لقد استخدمناها جميعًا في الفصل السابق.
بالنسبة للنقطة "  . " والخط المائل العكسي "  \ " ، فأنت لا تعرفهم ولكنك ستتعلمهم قريبًا.
حسنًا ، هذه شخصيات خاصة وكل منها يعني شيئًا معينًا. ماذا بعد؟

وبعد ذلك ، تقع المشكلة عليك في اليوم الذي تريده للبحث عن مثال " "Quoi ? في سلسلة.
كيف تكتب regex؟ هكذا ؟

#Quoi ?#
لا ، لا سيما! تُستخدم علامة الاستفهام ، كما تعلمون ، لتوضيح أن ما قبل الحرف هو اختياري (يمكن أن تظهر 0 أو 1 مرة). هنا ، ستكون المساحة الموجودة أمام علامة الاستفهام اختيارية ، ولكن هذا ليس ما نريد القيام به!

لذا ، كيف يمكننا أن نوضح أننا نبحث عن " "Quoi ? عندما علامة الاستفهام لديها بالفعل معنى؟
سيكون علينا الهروب منها . هذا يعني أنه يجب عليك فعلاً وضع شرطة مائلة للخلف "  \ " أمام رمز خاص. لذلك ، فإن regex الصحيح سيكون:

#Quoi \?#
هنا ، يُستخدم الخط المائل العكسي ليقول إن علامة الاستفهام بعدها ليست رمزًا خاصًا ، بل حرفًا مثل أي علامة أخرى!
إنه نفس الشيء بالنسبة لجميع الحروف الأولية الأخرى التي أظهرتها لك أعلاه (  # ! ^ $ ( ) [ ] { } ? + * . \) : عليك وضع شرطة مائلة عكسية في المقدمة إذا كنت تريد استخدامها في بحثك.

ستلاحظ أنه لاستخدام خط مائل عكسي ، فإنك بحاجة إلى ... مثل هذا: \\ .
ومع ذلك ، ما تحتاج إلى تذكره بسيط: إذا كنت تريد استخدام رمز خاص في بحثك ، فيجب أن تضع شرطة مائلة للخلف في المقدمة . شريط نقطة.

أعطيك بعض أمثلة للاستخدام ، يجب أن تجعلك تفكر في ذلك:
سلسلة Regex النتيجة
Je suis impatient ! #impatient \!# TRUE
Je suis (très) fatigué #\(très\) fatigué# TRUE
J'ai sommeil… #sommeil\.\.\.# TRUE
Le smiley :-\ #:-\\# TRUE
حالة الفئات
هناك شيء آخر يجب رؤيته (حالة خاصة أخرى) ، وهو يتعلق بفئات الرموز.

حتى الآن ، وضعت الأحرف والأرقام بين قوسين معقوفين ؛ على سبيل المثال:
#[a-z0-9]#

نعم ولكن ، كما يمكنك أن تتخيل ، لديك الحق في إضافة أحرف أخرى ، مثل لهجات (ولكن في هذه الحالة ، عليك إدراجها واحداً تلو الآخر). على سبيل المثال: [a-zéèàêâùïüë] وهلم جرا.
جيد حتى الان ولكن إذا كنت ترغب في إدراج أحرف خاصة أيضًا ، هاه؟ على سبيل المثال علامة استفهام (عشوائيا). حسنا ، هذا لا يعني شيئا !  لا حاجة للهروب من ذلك: داخل الاقواس المربعة metacharacters ... لا تعد !
وبالتالي ، تعمل
#[a-z?+*{}]#
هذه الطريقة بشكل جيد للغاية: فهذا يعني أن لدينا الحق في وضع خطاب أو علامة استفهام أو علامة +أو ما إلى ذلك.
3 حالات خاصة ، ولكن.
  • "  # " (Sharp) : يتم استخدامها دائمًا للإشارة إلى نهاية regex . لاستخدامها ، يجب وضع شرطة مائلة عكسية ، حتى في فئة الأحرف.
  • "  ] " (خطاف الإغلاق): عادة ، يشير خطاف الإغلاق إلى نهاية الفئة. إذا كنت ترغب في استخدامه كحرف تبحث عنه ، فهناك أيضًا شرطة مائلة للخلف.
  • "  - " (داش): حالة أخرى خاصة إلى حد ما. يتم استخدام الشرطة - كما تعلمون - لتحديد فاصل زمني للفئة  (مثل [a-z] ) . ماذا لو كنت تريد إضافة شرطة إلى قائمة الرموز المحتملة؟ حسنًا ، ضعها في بداية الفصل أو في النهاية. على سبيل المثال: [a-z0-9-]يسمح لك بالبحث عن حرف أو رقم أو شرطة.

فئات مختصرة


والخبر السار هو أنك الآن مستعد تقريبا للقيام بأي regex تريدها.
الأخبار السيئة هي أنني قلت فقط "تقريبا" .
اطمئن ، لن يمر وقت طويل ولن تشعر بأي ألم (في هذه المرحلة ، لم تعد تشعر بالألم على أي حال).
أريد فقط أن أريك ما يسمى بالفئات المختصرة ، وما أسميه اختصارات .
قد لا تكون بعض هذه الاختصارات ضرورية بالنسبة لك ، ولكن نظرًا لأنك قد تصادفها عاجلاً أم آجلاً ، لا أريد أن تفاجئك وتعتقد أنني أخفيت أشياء عنك.
إليك ما يجب تذكره:
الاختصار معنى
\d يشير إلى رقم.
هو بالضبط مثل الكتابة[0-9]
\ D يشير إلى ما ليس رقمًا.
انها مثل الكتابة[^0-9]
\w يشير إلى حرف أبجدي رقمي أو شرطة سفلية.
هذا يتوافق مع[a-zA-Z0-9_]
\ W يشير إلى ما ليست كلمة.
إذا تابعت ، فهو مثل الكتابة[^a-zA-Z0-9_]
\t يشير إلى علامة تبويب
\n يشير إلى سطر جديد
\r يشير إلى عودة السطر
\s يشير إلى مساحة بيضاء
\ S يشير إلى عدم وجود مساحة بيضاء ( \t \n \r)
. يشير إلى أي رمز.
لذلك يأذن بكل شيء!
هذه حروف عادية ، لكن عندما تضع خط مائل عكسي أمامها ، فإنها تُعطى معنى خاصًا.
إنه عكس ما فعلناه سابقًا: لقد استخدمنا شرطة مائلة عكسية أمام الحروف الأولية لإزالة معانيها الخاصة.
بالنسبة للنقطة ، هناك استثناء: فهو يشير إلى كل شيء ما عدا الإدخالات ( \n) .
لجعل النقطة تشير إلى كل شيء ، وحتى الإدخالات ، ستحتاج إلى استخدام الخيار "s" من PCRE . على سبيل المثال:
#[0-9]-.#s
هيا ، هذه المرة تعلمون بما فيه الكفاية ، سنكون قادرين على البدء في الممارسة التطبيقية!

بناءregex كاملة


ستفهم أخيرًا سبب سلبك طوال الوقت!
هذه المرة ، سوف نتطرق إلى أمثلة ملموسة ستكون بالتأكيد مفيدة لك. سنقوم ببناء regex معًا ، بحيث تفهم الطريقة. بعد ذلك سوف تكون قادرًا تمامًا على اختراع regex الخاص بك واستخدامه لنصوص PHP الخاصة بك!
رقم الهاتف
بالنسبة إلى هذا التسجيل الحقيقي الأول ، سنحاول معرفة ما إذا كان المتغير (الذي أدخله زائر عبر نموذج ، على سبيل المثال) يتوافق مع رقم هاتف.
سأضع نفسي على أرقام الهواتف الفرنسية ، وسيتعين عليك الاعتذار إذا لم تكن فرنسيًا ولا تعرفه. الميزة هي أنه يمكنك بعد ذلك التدرب على كتابة هذا التعبير عن أرقام هواتف بلدك.
للتذكير (ولمن لا يعرف ، لذلك) ، يحتوي رقم الهاتف الفرنسي على 10 أرقام. على سبيل المثال: "01 53 78 99 99". يجب مراعاة القواعد التالية:
  • الرقم الأول هو دائمًا 0
  • يذهب الرقم الثاني من 1 إلى 6 (1 لمنطقة باريس ... 6 للهواتف المحمولة) ، ولكن هناك أيضًا 8 (هذه أرقام خاصة). لاحظ أن 7 و 9 قد بدأت في الاستخدام ولكننا لن نأخذها في الاعتبار في الأمثلة لدينا ؛
  • ثم تأتي الأرقام الثمانية المتبقية (يمكنهم الانتقال من 0 إلى 9 دون مشكلة).
للبدء ، وللبساطة ، سنفترض أن المستخدم يدخل رقم الهاتف دون وضع أي مساحة أو أي شيء (لكننا نعقده مباشرة بعد ذلك ، وسترى أن هذا هو الاهتمام الحقيقي لـ regex ) .
لذلك يجب أن يبدو رقم الهاتف هكذا : "0153789999" . كيف تكتبون regex تتطابق مع رقم هاتف مثل هذا؟
إليكم كيفية المضي قدمًا من أجل بناء هذا regex .
  1. 1. أولاً ، نريد فقط رقم الهاتف. ولذا فإننا سوف نبدأ من خلال وضع رموز ^و $ لتحديد بداية ونهاية سلسلة:
    #^$# 
  2. 2. دعونا نكمل. نحن نعلم أن الحرف الأول هو بالضرورة 0. لذلك نكتب:

  3. #^0$# 
  4. 3. يتبع 0 عددًا يتراوح من 1 إلى 6 ، دون نسيان الرقم 8 للأرقام الخاصة. لذلك يجب أن نستخدم الفئة
     [1-68] الذي يعني "رقم من 1 إلى 6 أو 8":
    #^0[1-68]$# 
  5. ثم تأتي الأرقام الثمانية المتبقية ، والتي يمكن أن تتراوح من 0 إلى 9. لذلك علينا فقط أن نكتب   [0-9]{8} للإشارة إلى أننا نريد 8 أرقام. في النهاية ، يعطينا هذا regex :
وهذا كل شيء !
حسنًا ، أرى أنك في حالة جيدة ، لذلك دعونا لا نتوقف عند هذا الحد ونحسن هذا التعبير.
لنفترض الآن أن الشخص يمكنه كتابة مسافة كل رقمين (كما هو شائع في فرنسا) ، ولكن أيضًا فترة أو شرطة. لذلك سيتعين على regex قبول أرقام الهواتف التالية:
  • 01 53 78 99 99
  • 01-53-78-99-99
  • 01.53.78.99.99
  • 0153 78 99 99
  • 0153.78 99-99
  • إلخ
وهنا تكمن قوة regex !
الاحتمالات عديدة للغاية ، ومع ذلك فأنت تحتاج فقط إلى كتابة التعبير المقابل.
لذلك نستأنف إنشاء regex لدينا.
  1. أولاً ، الرقم 0 ثم الرقم من 1 إلى 6 دون أن ينسى 8. هذا لا يتغير:  #^0[1-68]$#
  2. بعد هذين الرقمين الأولين ، يمكن أن يكون هناك إما مساحة أو شرطة أو فترة أو أي شيء على الإطلاق (إذا كانت الأرقام مرفقة). لذلك سنستخدم الفئة [-. ] ( شرطة ، نقطة ، مسافة ) . 
    ولكن كيف نقول أن هذه النقطة (أو الشرطة ، أو مسافة) ليست إلزامية؟ مع علامة الاستفهام ، بالطبع! إنه يعطينا : #^0[1-68][-. ]?$#
  3. بعد أول شرطة (أو نقطة ، أو مسافة ، أو لا شيء) ، لدينا الرقمان التاليان. لذلك علينا أن نضيف
     [0-9]{2}إلى regex لدينا.
    #^0[1-68][-. ]?[0-9]{2}$#
    والآن فكر في الأمر. هناك طريقة للإنتهاء بسرعة: نحتاج فقط أن نقول "  [-. ]?[0-9]{2} " يجب أن تتكرر أربع مرات ، وأنتهت عملية regex الخاصة بنا! سنستخدم الأقواس لتطويق الكل ، ونضع علامة {4}مباشرة بعد الإشارة إلى أن كل هذا يجب أن يتكرر أربع مرات. مما يعطينا في النهاية:
    #^0[1-68]([-. ]?[0-9]{2}){4}$#
يمكنك تأطيرها بشكل أساسي عن طريق تعليقها في غرفتك: إنها أول regex حقيقي!
#^0[1-68]([-. ]?[0-9]{2}){4}$#
إليكم نصًا صغيراً قمت بإعداده بسرعة ، بحيث يمكنك اختبار كل قوة regex :

<p>
<?php
if (isset($_POST['telephone']))
{
    $_POST['telephone'] = htmlspecialchars($_POST['telephone']); 
/ / نجعل علامات HTML التي يمكن للزائر إدخالها غير ضارة
    if (preg_match("#^0[1-68]([-. ]?[0-9]{2}){4}$#", $_POST['telephone']))
    {
        echo 'Le ' . $_POST['telephone'] . ' رقم <strong>صحيح</strong> !';
    }
    else
    {
        echo 'Le ' . $_POST['telephone'] . ' ليس صحيحا !حاول ثانية  !';
    }
}
?>
</p>

<form method="post">
<p>
    <label for="telephone">رقم هاتفك ?</label> <input id="telephone" name="telephone" /><br />
    <input type="submit" value="راجع رقم الهاتف" />
</p>
</form>
يمكنك تجربة جميع أرقام الهواتف التي تريدها ، مع وجود مسافات في المنتصف أو لا إذا كنت تريد ذلك: يقوم regex بإدارة جميع الحالات.
يمكنك أيضًا استخدام الاختصار \d للإشارة إلى رقم في regex : #^0[1-68]([-. ]?\d{2}){4}$# شخصيًا ، أجد أن الوضع [0-9]لا يزال أكثر وضوحًا.
عنوان بريد إلكتروني
سيكون من المُؤسف التوقف بعد هذه البداية الجيدة .
لذلك سأعرض لك مثالًا ثانيًا سيكون بالتأكيد مفيدًا لك: اختبار ما إذا كان عنوان البريد الإلكتروني صالحًا أم لا .
لذلك ، قبل أن أبدأ أي شيء ، ولكي نتفق ، أذكرك بكيفية إنشاء عنوان بريد إلكتروني.
  1. بادئ ذي بدء ، لدينا اسم مستعار (حرف واحد على الأقل ، لكنه نادر الحدوث). يمكن أن يكون هناك أحرف صغيرة (لا توجد أحرف كبيرة) والأرقام والفواصل والشرطات والشرطات السفلية "  _ " .
  2. ثم هناك علامة : @ .
  3. ثم هناك اسم المجال. بالنسبة لهذا الاسم ، نفس القاعدة بالنسبة لاسم مستعار: الأحرف الصغيرة والأرقام والشرطات والنقاط والشرطات السفلية فقط. الفرق الوحيد - لا يمكنك تخمينه بالضرورة - هو وجود حرفين على الأقل (على سبيل المثال ، "a.com" غير موجود ، ولكن "aa.com" نعم) .
  4. أخيرًا ، هناك الامتداد (مثل ".fr" ) . هذا التمديد له فترة ، متبوعًا بحرفين إلى أربعة أحرف (صغيرة). في الواقع ، هناك ".es" ، ".de" ، ولكن أيضًا ".com" ، ".net" ، ".org" ، ".info" ، إلخ.
لذلك يمكن أن يبدو عنوان البريد الإلكتروني j.dupont_2@orange.fr .
دعنا نقوم ببناء regex .
  1. أولاً ، نريد عنوان البريد الإلكتروني فقط ؛ لذلك سوف نطلب أن تكون بداية ونهاية السلسلة:#^$# 
  2. ثم لدينا حروف وأرقام وشرطات ونقاط وشرطات سفلية ، مرة واحدة على الأقل. لذلك نستخدم الفصل [a-z0-9._-]الذي نضيف بعده العلامة +لطلب أن يكون هناك واحد على الأقل: #^[a-z0-9._-]+$# 
  3. ثم تأتي علامة (هناك ليست معقدة ، علينا فقط كتابة الحرف): #^[a-z0-9._-]+@$# 
  4. ثم سلسلة أخرى من الحروف والأرقام والنقاط والشرطات ، مرتين على الأقل. لذلك نحن نكتب {2,}ليقول "مرتين أو أكثر": #^[a-z0-9._-]+@[a-z0-9._-]{2,}$# 
  5. ثم تأتي النقطة (من ".fr" على سبيل المثال). كما قلت لك أعلاه ، هو حرف خاص يستخدم للإشارة إلى "أي رمز" (حتى لهجات). الآن ، هنا ، نريد إزالة معناها في هذه النقطة لنقول أننا نريد نقطة الرمز في regex لدينا. لذلك سنضع خط مائل عكسي أمامها: #^[a-z0-9._-]+@[a-z0-9._-]{2,}\.$# 
  6. أخيرًا ، في النهاية ، نحتاج إلى حرفين إلى أربعة أحرف. إنها بالضرورة أحرف صغيرة ، وهذه المرة بلا رقم أو شرطة ، إلخ. لذلك نكتب: #^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$# 
وهنا هو regex الجديد!
#^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$#
تشعر أنك بدأت تتحدث الصينية ، أليس كذلك؟ ؛-)
هيا ، أنا في حالة جيدة وفي حالة مزاجية جيدة ، أنا أعطيك نص PHP لاختبار هذا regex :

<p>
<?php
if (isset($_POST['mail']))
{
    $_POST['mail'] = htmlspecialchars($_POST['mail']); 
/ / نجعل علامات HTML التي يمكن للزائر إدخالها غير ضارة
    if (preg_match("#^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$#", $_POST['mail']))
    {
        echo 'L\'adresse ' . $_POST['mail'] . ' <strong>صالح</strong> !';
    }
    else
    {
        echo 'L\'adresse ' . $_POST['mail'] . ' ليس صالحا حاول ثانية !';
    }
}
?>
</p>

<form method="post">
<p>
    <label for="mail">بريدك الالكتروني ?</label> <input id="mail" name="mail" /><br /> 
    <input type="submit" value="تثبت من العنوان الالكتروني" />
</p>
</form>
لذلك عناوين الاختبار مثل:
  • the_cypher@hotmail.com.
  • business_consultants@free4work.info.
  • mega-killer.le-retour@super-site.fr.st.
  • الخ
هل احببتها؟
أدرك أن الأمر يبدو معقدًا جدًا عند قراءة regex في المرة الأولى. أتصور الرأس الذي يجب أن يكون لديك عندما عرضت عليك regex في مقدمة الفصل السابق. ؛-)

لكن مهلا ، هل يمكنك رؤية التقدم؟ لقد كتبنا للتو واحدة من الأشياء الشهيرة غير القابلة للكسر معًا ، ولا أعتقد أن الكثير منكم اعتقد أنه ستصل إلى هناك من خلال قراءة الفصل السابق!
ومع ذلك نحن هنا: تمكنا من كتابة اثنين من regexes كاملة. لن أجعلك تعمل على الثلث ، فهمت - كما أعتقد - فهمت المبدأ وتعرف كيف تتعامل مع الكبار.

أريد فقط أن أوضح لك شيئًا أخيرًا قبل الانتقال إلى آخر مفهوم مهم (الالتقاط والاستبدال).
regex ... مع MySQL !
مثل ما ، سوف تكون سعيدًا حقًا بالوصول إلى هنا.

نعم ، نبأ عظيم: MySQL يفهم regex !

وهذا جيد للجميع: لقد تعلمت للتو كتابة regex ، لم يعد لديك شيء تقريبًا لتستخدمه مع MySQL .

ومع ذلك ، يجب أن تعلم أن MySQL لا يفهم سوى لغة regex بلغة POSIX ، وليس PCRE كما تعلمنا.

تحتاج فقط إلى تذكر ما يلي لإنشاء POSIX regex :
  • لا يوجد محدد أو خيارات. لذلك لا نُحيط regex بالرموز # .
  • لا توجد فصول مختصرة كما رأينا أعلاه ، لذلك لا \d، إلخ. من ناحية أخرى ، يمكنك دائمًا استخدام النقطة ليقول: "أي رمز" .
الأفضل ، بالطبع ، هو دائمًا مثال جيد. افترض أنك قمت بتخزين عناوين IP للزائرين في جدول visiteurs وتريد أسماء الزوار الذين تبدأ عناوين IP الخاصة بهم بـ "84.254":

    SELECT nom FROM visiteurs WHERE ip REGEXP '^84\.254(\.[0-9]{1,3}){2}$'	
هذا يعني: حدد جميع أسماء الجدول visiteurs التي يبدأ IP الخاص بها بـ "84.254" وينتهي برقمين آخرين من رقم واحد إلى ثلاثة أرقام (على سبيل المثال: 84.254.6.177) .

كل قوة regex في استعلام MySQL لإجراء بحث دقيق للغاية ... لا يمكن رفضه. ؛-)
أنا لا أتحدث عن ذلك ، وأنا أعلم أنك سوف تتدبر أمرك إذا كان من المفيد لك.

الآن دعنا ننتقل إلى المفهوم المهم الأخير مع regex : "الالتقاط والاستبدال"!

الالتقاط والاستبدال



لقد أخبرتك في بداية هذين الفصلين المخصصين لإعادة التوثيق أنه تم استخدامها لإجراء بحث قوي (كما رأينا للتو ، من خلال أمثلة الهاتف والبريد) ، ولكن أيضًا لإجراء البحث و الاستبدال.
هذا سيسمح لنا على سبيل المثال بالقيام بما يلي:
  1. البحث عن عناوين البريد الإلكتروني في رسالة تركها زائر ؛
  2. تعديل رسالته تلقائيا لوضع رابط
<a href="mailto:blabla@truc.com">أمام كل عنوان ، مما سيجعل عناوين البريد الإلكتروني قابلة للنقر!
باستخدام هذه التقنية ، يمكننا أن نفعل الشيء نفسه لجعل الروابط http:// قابلة للنقر تلقائيًا أيضًا. يمكننا أيضًا ، كما سترى ، إنشاء لغة مبسطة خاصة بنا للزائر ، مثل bbCode الشهير المستخدم في معظم المنتديات (لتضعه [b][/b]بالخط العريض ، هل هذا يعني شيئًا لك؟) .
الأقواس المُلتقطة The captivating parentheses
كل شيء سنراه الآن يدور حول أقواس. لقد استخدمتها بالفعل لتطويق جزء من regex الخاص بك وتقول إنه كان عليها أن تكرر نفسها أربع مرات على سبيل المثال (كما فعلنا لرقم الهاتف).

حسنًا ، هذا هو الاستخدام الرئيسي للأقواس ، لكن يمكن استخدامها أيضًا لأغراض أخرى .
من الآن فصاعدًا ، سنعمل مع الوظيفة preg_replace .

من خلال هذه الوظيفة ، سنكون قادرين على تنفيذ ما يسمى "التقاط" السلسلة.
ما يجب أن تعرفه هو أنه في كل مرة تستخدم فيها أقواس ، فإنها تخلق "متغير" يحتوي على ما يحيط بها.

أشرح نفسي مع regex :
#\[b\](.+)\[/b\]#

يجب ألا تواجه مشكلة كبيرة في فك تشفيرها: فهذا يعني "  البحث في السلسلة لأحدهم [b]، متبوعًا بحرف واحد أو أكثر (تشير النقطة إلى" أي شيئ ") ، متبوعًا بـ [/b]   .
اضطررت إلى وضع خطوط مائلة عكسية "  \ " أمام الأقواس بحيث لا يخلط PHP بينها وبين فئات الأحرف (مثل [a-z] ).

عادة ، إذا كنت تعتقد لمدة ثانيتين ، عليك أن تخبر نفسك أن الأقواس ليست إلزامية هنا. وصحيح أنه لإجراء بحث فقط ، فإن الأقواس عديمة الجدوى بالفعل. ولكن لاستعمال الاستبدال ، ستكون مهمة جدا !
في الحقيقة ، تذكر ذلك: في كل مرة يوجد فيها قوس ، فإنه ينشئ متغيرًا يسمى $1 (للقسم الأول) ، $2 وللثاني ، إلخ.

سنستخدم هذه المتغيرات لتعديل السلسلة (عمل بديل).
على regex الذي أظهرته أعلاه ، يوجد قوس واحد فقط ، هل توافق؟ لذلك سيكون هناك متغير واحد فقط $1، والذي سوف يحتوي على ما هو بين [b]و [/b] . وبفضل ذلك ، نعرف ما الذي سنضعه بالخط العريض.

حسنًا ، نظرية كل هذا صعبة التفسير ، لذلك سأوضح لك على الفور كيف نضع بالعريض كل الكلمات بين [b][/b] :

<?php
$texte = preg_replace('#\[b\](.+)\[/b\]#i', '$1', $texte);
?>
إليك كيفية استخدام الوظيفة preg_replace .
  1. نعطيها لأول مرة regex . لا شيء خاص، كما ترون، إلا أنه يجب أن نضع في اعتبارنا أن كل قوس سيخلق متغير ( $1 ، $2، الخ) .    هنا ، أضفت الخيار "i" بحيث يعمل الرمز أيضًا مع الأحرف الكبيرة ( [B][/B]) .
  2. ثم ، وهذا هو المكان الجديد ، نشير إلى النص البديل : " <strong>$1</strong> " (أذكرك بأنه <strong>يسمح بالخط العريض بتنسيق  HTML ) .  بين علامات HTML ، أنا وضعت $1 . هذا يعني أن ما هو موجود في قوس الالتقاط ( بين [b]و [/b] ) سيحيط به بالفعل علامات <strong>  !
  3. أخيرًا ، المُدخل الأخير هو النص الذي نقوم به بالبحث / الاستبدال (هذا ، كما تعلمون بالفعل).
تقوم الدالة preg_replace بإرجاع النتيجة بعد إجراء الاستبدال.
إذا قمت بتنظيم العملية ، فإنها تعطي الشكل التالي.
web dynamique php
كيف يعمل preg_replace
هناك بعض القواعد التي يجب عليك اتباعها لتتعلمها.
  • إذا كان لديك العديد من الأقواس ، لمعرفة عدد واحد منهم فقط عدهم بالترتيب من اليسار إلى اليمين. على سبيل المثال : #(anti)co(nsti)(tu(tion)nelle)ment# هناك أربعة أقواس في هذه التعابير المنطقية (أي $1، $2، $3و $4 ) . يحتوي الأقواس رقم 3 ( $3) على ""tutionnelle ، $4 ويحتوي القوس على ""tion . تذكر أنه الترتيب الذي يتم به فتح الأقواس هو أمر مهم.
  • يمكنك استخدام حتى 99 أقواس ملتقطة في regex ( مما يترك لك مساحة) . لذلك تستعمل الى حدود $99 .
  • يتم إنشاء متغير$0 دائمًا ؛ أنه يحتوي على كل regex . على نفس المثال كما في وقت سابق:
    #(anti)co(nsti)(tu(tion)nelle)ment# ...  $0 يحتوي على ""anticonstitutionnellement .
  • إذًا ، إذا كنت لا تريد أن يكون القوس ملتقط (لتسهيل حساباتك ، أو لأن لديك الكثير من الأقواس) ، فيجب أن يبدأ بعلامة استفهام متبوعة بنقطتين "   ": . مثلا :
#(anti)co(?:nsti)(tu(tion)nelle)ment# القوس الثاني ليس ملتقط. لدينا فقط ثلاثة متغيرات متبقية (أربعة إذا حسبنا $0 ):
  1. $0  : anticonstitutionnellement
  2. $1   : anti
  3. $2  : tutionnelle
  4. $3   : tion
ها هي: إذا فهمت ذلك ، فهمت كل شيء ، أحسنت! ؛-)
إنشاء bbCode الخاص بك
يمكننا الآن الانتقال إلى الممارسة وتعلم استخدام الأقواس المُلتقطة.
سنقوم بتنفيذ ما يسمى المحلل اللغوي  (parser).
سيتم استخدام المحلل اللغوي لتحويل النص الذي كتبه زائر (للحصول على رسالة في منتدى أو في سجل زوارك أو حتى في الدردشة المصغرة!) في نص غير ضار (بدون علامات HTML بفضل htmlspecialchars) ولكن يقبل أيضا bbCode !
لن نقوم بكل رموز bbC الموجودة (طويلة جدًا) ، ولكن للتدريب ، ستكون هذه كافية بالفعل:
  • [b][/b]  : لوضع نص غامق.
  • [i][/i]  : لوضع النص بخط مائل ؛
  • [color=red][/color]  : لتلوين النص (سيكون عليك ترك الاختيار بين عدة ألوان).
وسنتأكد أيضًا من استبدال عناوين URL ( http://) تلقائيًا بروابط قابلة للنقر.
لنبدأ مع [b] و  [i] (إنه نفس الشيء) .
كنت قد رأيت رمز [b]، وهذا هو في الواقع تقريبا جيد. هناك مشكلة ، مع ذلك: هناك نقص في الخيارات. لكي ينجح هذا ، سنحتاج إلى استخدام ثلاثة خيارات:
  • i : لقبول الأحرف الكبيرة والصغيرة ( [B]و [b]) ؛
  • s : بحيث تعمل "النقطة" أيضًا مع فواصل الأسطر (بحيث يكون النص غامقًا على عدة أسطر) ؛
  • U : الحرف U الكبيرة هي خيار لا تعرفه ويعني "Ungreedy" ("ليس جشعًا"). سأنشر التفسيرات المعقدة إلى حد ما حول كيفية عملها ، لكنني أعلم أنه ، بشكل عام ، لن ينجح بشكل صحيح إذا كان هناك العديد من [b]النص. على سبيل المثال:
" Ce texte est [b]important[/b], il faut me [b]comprendre[/b] ! " ...
بدون تنشيط خيار "Ungreedy" ، كان regex يرغب في وضع كل ما هو غامق بين [b] الأول والأخير [/b] ( أي " important[/b], il faut me [b]comprendre " ) . باستخدام خيار "U" ، ستتوقف regex مع أول [/b]، وهذا ما نريده.
هنا هو الكود الصحيح للأحرف العريضة والمائلة مع bbCode :

<?php
$texte = preg_replace('#\[b\](.+)\[/b\]#isU', '$1', $texte);
$texte = preg_replace('#\[i\](.+)\[/i\]#isU', '$1', $texte);
?>
كما ترون ، هو نفسه تمامًا لـ [b]و [i] (باستثناء أن علامة HTML التي نستخدمها هي <em> ).
لذلك إذا كنت قد تابعت حتى الآن ، فلن يفاجئك هذا كثيرًا.
الآن دعنا ننتقل إلى حالة أكثر تعقيدًا: حالة العلامة [color=truc] . سنترك الاختيار بين عدة ألوان مع الرمز "  | " (OR) ، وسنستخدم اثنين من الأقواس:
  1. أول من يسترد اسم اللون الذي تم اختياره (باللغة الإنجليزية ، لذلك لن نحتاج إلى تغييره لكود HTML ) ؛
  2. الثاني لاسترداد النص بين [color=truc]و  [/color] (كما هو الحال مع غامق ومائل) .
هذه هي النتيجة:

<?php
$texte = preg_replace('#\[color=(red|green|blue|yellow|purple|olive)\](.+)\[/color\]#isU', '$2', $texte);
?>
لذلك ، إذا كتبنا
[color=blue]texte[/color]
، فسوف يكتب texte باللون الأزرق. يمكنك تجربة الألوان الأخرى أيضًا!
اذهب ، الخطوة الأخيرة ، وبعد ذلك أتركك تحاول.
أريد أن http:// يتم تحويل الروابط تلقائيًا إلى روابط قابلة للنقر. حاول كتابة regex ، يمكنك أن تفعل ذلك!
هنا هو الحل:

<?php
$texte = preg_replace('#http://[a-z0-9._/-]+#i', '$0', $texte);
?>
في النص البديل ، استخدمت $0، إذا كنت تتذكر بشكل صحيح ، يأخذ كل النص المعترف به من قبل regex (حتى هنا ، URL بالكامل) .
لا توجد خيارات "s" و "U" لأننا لم ننقطع مطلقًا في منتصف عنوان URL ، ولا يتم استخدام وضع "Ungreedy" هنا (جرب استخدام U ، سترى ذلك ينتهي الرابط في الحرف الأول! ) .
ستلاحظ أنني جعلت الأمر بهذه البساطة. هذا صحيح ، كان بإمكاني جعله أكثر تعقيدًا ودقة ، لكنني لا أريد أن أربكك بهذا الأمر: أنا أريد منك تحسينه بشكل خاص.
في الواقع ، فإن regex يعمل بشكل جيد للغاية  http://www.arabclassroom.com/images/super_image2.jpg ، لكنه لا يعمل إذا كانت هناك متغيرات في المُدخلات في URL ، مثل على سبيل المثال:

http://www.arabclassroom.com/index.php?page=3&skin=blue
أترك الأمر لك لتحسين regex ، وسوف تفعل القليل من العمل.
الآن دعنا نلخص محلل bbCode بأكمله:


<?php
if (isset($_POST['texte']))
{
    $texte = stripslashes($_POST['texte']); 
// نزيل الخطوط المائلة التي كان من الممكن إضافتها تلقائيًا
    $texte = htmlspecialchars($texte); 
// نجعل علامات HTML التي يمكن للزائر إدخالها غير ضارة
    $texte = nl2br($texte); // نقوم بإنشاء <br /> للحفاظ على فواصل الأسطر
    
    // regex نمرر نصنا إلى  
    $texte = preg_replace('#\[b\](.+)\[/b\]#isU', '<strong>$1</strong>', $texte);
    $texte = preg_replace('#\[i\](.+)\[/i\]#isU', '<em>$1</em>', $texte);
    $texte = preg_replace('#\[color=(red|green|blue|yellow|purple|olive)\](.+)\[/color\]#isU', '<span style="color:$1">$2</span>', $texte);
    $texte = preg_replace('#http://[a-z0-9._/-]+#i', '<a href="$0">$0</a>', $texte);

    echo $texte . '<br /><hr />';
}
?>

<p>
مرحبًا بك في Parser! <br />
     لقد كتبنا هذا المحلل اللغوي معًا ، أتمنى أن تستمتع برؤية أن كل ما تعلمته سيكون مفيدًا جدًا لك!</p>

<p> استمتع باستخدام bbCode. اكتب على سبيل المثال:</p>

<blockquote style="font-size:0.8em">
<p>
    أنا [b]مبتدأ[/b], و لكنني [i]تعلّمت كل شيء[/i] على http://www.arabclassroom.com<br />
    انصحك [b][color=green]بزيارة[/color][/b] الموقع, تستطيع ان تتعلم [i][color=purple]انت ايضا[/color][/i] !
</p>
</blockquote>

<form method="post">
<p>
    <label for="texte">رسالتك ?</label><br />
    <textarea id="texte" name="texte" cols="50" rows="8"></textarea><br />
    <input type="submit" value=" regexأظهر قوة " />
</p>
</form>
?>
web dynamique php
اختبار محلل BbCode
حسنًا ، إذا لم تصنع موقعًا رائعًا بعد كل الذي تعلّمته ، فلن أستطيع فعل أي شيء من أجلك.
قبل أن أنهي ، أخشى أنك قد تشعر بالملل ، أقدم لك بعض أفكار regex أدناه التي يمكنك إضافتها إلى المحلل اللغوي.
  • سبق أن أخبرتكم أعلاه ، لكن سيكون من الجيد جدًا أن تعمل عناوين URL القابلة للنقر أيضًا على عناوين URL ذات متغيرات مثل: http://www.arabclassroom.com/index.php?page=3&skin=blue.
  • يجب عليك أيضًا تحليل عناوين البريد الإلكتروني من خلال ربطها mailto : !
  • وسيكون لطيفا لإكمال الكود مع [u]، [img]الخ
ولكن بما أننا هناك ، فلماذا أعيد bbCode؟ بعد كل شيء، إذا كانت لديهم حساسية منالاقواس المربعة، لأن [b]لا يعني شيئا، لمجرد اختراع الرمز: {gras} {/gras} .
  • وإذا كنت تحب regex ، يمكنني أن أقدم لك تحديًا أخيرًا يجب أن يشغلك لفترة قصيرة: كتابة وظيفة تلوين رمز HTML تلقائيًا!
أنت تعطي الوظيفة رمز HTML ، وتكوّنها htmlspecialchars ، ثم تضيف بعضها <span style="color:…"> إلى اللون ، على سبيل المثال باللون الأزرق ، أسماء العلامات ، باللون الأخضر ، باللون الأحمر ، ما هو في علامات الاقتباس ، إلخ.
حظا سعيدا ! سوف تحتاجها!

في الخلاصة


  • بعض الأحرف خاصة ضمن تعبير منتظم: نحن نتحدث عن الحروف الأولية. إذا كنت تريد البحث عنها في سلسلة ، فيجب عليك الهروب منها بوضع رمز شرطة مائلة للخلف في المقدمة. على سبيل المثال: \[ .
  • هناك فئات مختصرة ، أي الفئات الجاهزة ، مثل على سبيل المثال  \d التي ترقى إلى الكتابة [0-9] .
  • preg_replace تتيح لك الوظيفة إجراء بدائل في سلسلة نصية.
  • في حالة الاستبدال ، تتيح لك الأقواس الموجودة في تعبير عادي التقاط جزء من النص لإعادة استخدامه في سلسلة أخرى.