Majid Al-RaimiRegular expressions: the core syntaxالتعابير النمطية (Regex): الصياغة الأساسية

ICS 582Lecture 02المحاضرة 02Part 08الجزء 08

Regular expressions: the core syntaxالتعابير النمطية (Regex): الصياغة الأساسية

From ELIZA's pattern rules to the building blocks of regular expressions: literals, bracket classes, ranges, negation, quantifiers, wildcards, anchors and the backslash aliases.من قواعد الأنماط في ELIZA إلى اللبنات الأساسية للتعابير النمطية: الحروف الحرفية (literals)، وفئات الأقواس، والنطاقات، والنفي، والمكممات (quantifiers)، والرمز العام (wildcard)، والمرتكزات (anchors)، واختصارات الشرطة المائلة العكسية.

Conceptsالمفاهيم
4
Slidesالشرائح
56-65
Readingمدة القراءة
24 min24 دقيقة
Understoodما فهمته
0/4 conceptsمفاهيم

Why this part mattersلماذا يهمّ هذا الجزء

Every tokenizer you will build or inspect, every corpus cleaning script for Arabic or English, every date or number normalizer, and every exam question on this chapter runs through the same ten or so symbols. The GPT-2 pre-tokenizer later in this lecture is one regular expression. Edit distance in the next parts starts from tokens that a regex produced.

This part builds the core syntax from the ground up, starting with the program that made pattern matching famous. ELIZA held conversations in 1966 using nothing but keyword rules and text substitution, and people believed it understood them. From there we take the symbols one family at a time: literals and disjunction, bracket classes, quantifiers and the wildcard, anchors and the backslash aliases. The next part adds precedence, groups, substitution and lookahead on top of exactly this vocabulary, so every table here is worth being able to reproduce from memory. A live tester at the end of the part loads every example row from the slides so you can check each first match yourself.

كل tokenizer ستبنيه أو تفحصه، وكل سكربت لتنظيف مدوّنة نصوص عربية أو إنجليزية، وكل أداة لتوحيد صيغ التواريخ أو الأرقام، وكل سؤال امتحان عن هذا الفصل، يمر كله عبر الرموز العشرة تقريبًا نفسها. الـ pre-tokenizer الخاص بـ GPT-2 الذي سيأتي لاحقًا في هذه المحاضرة هو تعبير نمطي واحد. ومسافة التحرير (edit distance) في الأجزاء القادمة تبدأ من وحدات (tokens) أنتجها regex.

يبني هذا الجزء الصياغة الأساسية من الصفر، بدءًا بالبرنامج الذي جعل مطابقة الأنماط مشهورة. فقد أجرى ELIZA محادثات عام 1966 بلا شيء سوى قواعد كلمات مفتاحية واستبدال نصوص، وصدّق الناس أنه يفهمهم. ثم نأخذ الرموز عائلةً عائلة: الحروف الحرفية والاختيار، وفئات الأقواس، والمكمِّمات والرمز الشامل، والمراسي واختصارات الشرطة المائلة العكسية. الجزء التالي يضيف الأولوية والمجموعات والاستبدال والنظر للأمام (lookahead) فوق هذه المفردات بالضبط، لذلك يستحق كل جدول هنا أن تقدر على إعادة كتابته من الذاكرة. وفي نهاية الجزء أداة اختبار حية تحمّل كل مثال من الشرائح لتتحقق من كل مطابقة أولى بنفسك.

By the end you canفي نهاية هذا الجزء ستستطيع

  1. Explain how ELIZA produced replies from keyword substitution rules and name the Eliza effect.اشرح كيف كان ELIZA يولّد ردوده من قواعد استبدال تطلقها كلمات مفتاحية، وسمِّ ظاهرة Eliza effect.
  2. Read and write literals, concatenation, disjunction and bracket classes, including ranges and negation.اقرأ واكتب الحروف الحرفية (literals) والتسلسل (concatenation) والاختيار (disjunction) وفئات الأقواس، بما فيها النطاقات والنفي.
  3. Apply * + ? {n} {m,n} and the wildcard, and predict greedy versus lazy matches on a given string.طبّق * + ? {n} {m,n} والرمز الشامل (wildcard)، وتنبأ بالمطابقة الجشعة (greedy) مقابل الكسولة (lazy) على نص معطى.
  4. Use ^ $ \b to match whole words and line-based formats, and explain why anchors consume no characters.استخدم ^ $ \b لمطابقة كلمات كاملة وصيغ قائمة على الأسطر، واشرح لماذا لا تستهلك المراسي (anchors) أي حرف.
  5. Expand each alias \d \D \w \W \s \S and state where Python and JavaScript flavors differ.افرد كل اختصار \d \D \w \W \s \S إلى فئته، وبيّن أين تختلف نسختا Python و JavaScript.

In 1966 Joseph Weizenbaum at MIT published a program that imitated a Rogerian psychotherapist, the kind of therapist who reflects the patient's own words back as questions. He called it ELIZA. Read the exchange below as a patient would have, one line at a time.

في عام 1966 نشر Joseph Weizenbaum في MIT برنامجًا يقلّد معالجًا نفسيًا من مدرسة Rogerian، وهو نوع من المعالجين يعكس كلمات المريض نفسها ويعيدها إليه على هيئة أسئلة. سمّاه ELIZA. اقرأ المحادثة أدناه كما كان سيقرؤها مريض، سطرًا بعد سطر.

SpeakerالمتحدثLineالسطر
UserالمستخدمI need some help, that much seems certain.I need some help, that much seems certain.
ELIZAELIZAWHAT WOULD IT MEAN TO YOU IF YOU GOT SOME HELPWHAT WOULD IT MEAN TO YOU IF YOU GOT SOME HELP
UserالمستخدمPerhaps I could learn to get along with my mother.Perhaps I could learn to get along with my mother.
ELIZAELIZATELL ME MORE ABOUT YOUR FAMILYTELL ME MORE ABOUT YOUR FAMILY
UserالمستخدمMy mother takes care of me.My mother takes care of me.
ELIZAELIZAWHO ELSE IN YOUR FAMILY TAKES CARE OF YOUWHO ELSE IN YOUR FAMILY TAKES CARE OF YOU
UserالمستخدمMy father.My father.
ELIZAELIZAYOUR FATHERYOUR FATHER
UserالمستخدمYou are like my father in some ways.You are like my father in some ways.
The ELIZA transcript on slide 56, with Weizenbaum's original spelling restored on line 6محادثة ELIZA في الشريحة 56، مع استعادة تهجئة Weizenbaum الأصلية في السطر 6

It reads like attention. It is not. The whole program is a list of keywords, and for each keyword a small set of decomposition rules that split the input around the keyword, paired with reassembly rules that build a reply out of the pieces. Weizenbaum wrote the rules in his own notation. A decomposition rule such as (0 YOU 0 ME) means "an indefinite number of words, then YOU, then an indefinite number of words, then ME", and its reassembly rule (WHAT MAKES YOU THINK I 3 YOU) inserts the third component, whatever words stood between YOU and ME, into a fixed frame (Weizenbaum, 1966, p. 38). The dictionary he had built "so far" contained about 50 keywords. Nothing is parsed, nothing is understood, and the program has no memory of what "mother" means beyond the fact that it is filed under FAMILY.

تبدو كأنها إصغاء واهتمام، وليست كذلك. البرنامج كله قائمة من الكلمات المفتاحية، ولكل كلمة مفتاحية مجموعة صغيرة من قواعد التفكيك (decomposition rules) التي تقسم المُدخل حول الكلمة المفتاحية، ومعها قواعد إعادة التركيب (reassembly rules) التي تبني ردًا من القطع. كتب Weizenbaum القواعد بترميزه الخاص. قاعدة تفكيك مثل (0 YOU 0 ME) تعني «عدد غير محدد من الكلمات، ثم YOU، ثم عدد غير محدد من الكلمات، ثم ME»، وقاعدة إعادة التركيب المرافقة لها (WHAT MAKES YOU THINK I 3 YOU) تُدخل المكوّن الثالث، أي الكلمات التي وقعت بين YOU وME أيًا كانت، في إطار ثابت (Weizenbaum, 1966, p. 38). والقاموس الذي كان قد بناه «حتى الآن» ضم نحو 50 كلمة مفتاحية. لا يُحلَّل شيء نحويًا، ولا يُفهم شيء، والبرنامج لا يعرف عن معنى «mother» شيئًا سوى أنها مصنّفة تحت FAMILY.

Jurafsky and Martin rewrite the same idea in modern regular expression syntax, and this is the version to remember. After the input is uppercased and pronouns are swapped (I'M becomes YOU ARE, MY becomes YOUR), rules like these run in order until one fires (SLP3, section 2.6.7):

يعيد Jurafsky وMartin كتابة الفكرة نفسها بصياغة regular expression الحديثة، وهذه هي النسخة التي يجب أن تتذكرها. بعد تحويل المُدخل إلى حروف كبيرة وتبديل الضمائر (I'M تصبح YOU ARE، وMY تصبح YOUR)، تُجرَّب قواعد كهذه بالترتيب حتى تنطلق إحداها (SLP3, section 2.6.7):

  • re.sub(r".* YOU ARE (DEPRESSED|SAD) .*", r"I AM SORRY TO HEAR YOU ARE \1", input)re.sub(r".* YOU ARE (DEPRESSED|SAD) .*", r"I AM SORRY TO HEAR YOU ARE \1", input)
  • re.sub(r".* ALWAYS .*", r"CAN YOU THINK OF A SPECIFIC EXAMPLE", input)re.sub(r".* ALWAYS .*", r"CAN YOU THINK OF A SPECIFIC EXAMPLE", input)

Worked exampleمثال محلول

One ELIZA reply, step by stepرد واحد من ELIZA خطوة بخطوة

  1. User typesالمستخدم يكتب

    He says I'm depressed much of the time.
    He says I'm depressed much of the time.
  2. Uppercaseالتحويل إلى حروف كبيرة

    HE SAYS I'M DEPRESSED MUCH OF THE TIME.
    HE SAYS I'M DEPRESSED MUCH OF THE TIME.
  3. Swap pronounsتبديل الضمائر

    I'M becomes YOU ARE: HE SAYS YOU ARE DEPRESSED MUCH OF THE TIME.
    I'M تصبح YOU ARE: HE SAYS YOU ARE DEPRESSED MUCH OF THE TIME.
  4. Try the rules in orderجرّب القواعد بالترتيب

    The pattern .* YOU ARE (DEPRESSED|SAD) .* matches: .* swallows HE SAYS, the literal YOU ARE matches, the parenthesized alternative picks DEPRESSED, and the trailing .* swallows the rest.
    النمط .* YOU ARE (DEPRESSED|SAD) .* يطابق: .* يبتلع HE SAYS، والنص الحرفي YOU ARE يطابق، والبديل بين القوسين يختار DEPRESSED، و.* الأخيرة تبتلع الباقي.
  5. Reassembleإعادة التركيب

    The replacement I AM SORRY TO HEAR YOU ARE \1 copies whatever the parentheses captured into the slot marked \1.
    نص الاستبدال I AM SORRY TO HEAR YOU ARE \1 ينسخ ما التقطه القوسان، أيًا كان، إلى الخانة المعلَّمة بـ \1.
  6. Resultالنتيجة

    I AM SORRY TO HEAR YOU ARE DEPRESSED, which is the reply SLP3 derives in section 2.6.7 and the fourth reply in Weizenbaum's opening transcript. Swap DEPRESSED for SAD in the input and the same rule prints SAD.
    I AM SORRY TO HEAR YOU ARE DEPRESSED، وهو الرد الذي يستنتجه SLP3 في القسم 2.6.7، وهو أيضًا الرد الرابع في محادثة Weizenbaum الافتتاحية. استبدل DEPRESSED بـ SAD في المُدخل وستطبع القاعدة نفسها SAD.
The parenthesized alternative captures DEPRESSED, and the reassembly frame copies it into the reply. Nothing else in the sentence is read.البديل بين القوسين يلتقط DEPRESSED، وإطار إعادة التركيب ينسخها إلى الرد. لا يُقرأ أي شيء آخر في الجملة.
Weizenbaum (1966)Weizenbaum (1966)MeaningالمعنىModern regexالـ regex الحديث
0 in a decomposition rule0 في قاعدة تفكيكAn indefinite number of wordsعدد غير محدد من الكلمات.*.*
A positive integer n in a decomposition ruleعدد صحيح موجب n في قاعدة تفكيكExactly n wordsn كلمة بالضبط((?:\S+ ){n}), one group holding exactly n words((?:\S+ ){n})، مجموعة واحدة تحمل n كلمة بالضبط
3 in a reassembly rule3 في قاعدة إعادة تركيبInsert the third component the decomposition foundأدخِل المكوّن الثالث الذي وجده التفكيك\1 style backreference to a capture groupإحالة خلفية (backreference) بأسلوب \1 إلى مجموعة التقاط
Keyword dictionary, about 50 entriesقاموس الكلمات المفتاحية، نحو 50 مدخلًاWhich rule set to try, ranked by keywordأي مجموعة قواعد تُجرَّب، مرتبةً حسب الكلمة المفتاحيةA cascade of re.sub calls tried in orderسلسلة من استدعاءات re.sub تُجرَّب بالترتيب
Weizenbaum's 1966 notation next to the regex you would write todayترميز Weizenbaum عام 1966 بجانب الـ regex الذي ستكتبه اليوم

The parentheses and the \1 are a capture group and a Backreference, which the next part treats properly. For now the point is the shape of the machine: a keyword selects a rule, a pattern with wildcards splits the sentence, a frame reassembles the pieces. Weizenbaum's paper opens with the exchange "Men are all alike." answered by "IN WHAT WAY", and the reply is not about men at all: a rule keyed on the wording of the input prints a fixed question with no slot to fill.

القوسان و\1 هما capture group (مجموعة التقاط) وbackreference (إحالة خلفية)، وسيعالجهما الجزء التالي كما ينبغي. المهم الآن هو شكل الآلة: كلمة مفتاحية تختار قاعدة، ونمط فيه رموز شاملة يقسم الجملة، وإطار يعيد تركيب القطع. تبدأ ورقة Weizenbaum بالحوار «Men are all alike.» الذي يجاب عنه بـ «IN WHAT WAY»، والرد لا علاقة له بالرجال أصلًا: قاعدة مرتبطة بصياغة المُدخل تطبع سؤالًا ثابتًا ليس فيه خانة تُملأ.

Why people believed itلماذا صدّقه الناس

Crude as the rules were, SLP3 notes that many people who talked to ELIZA came to believe that it really understood them, and that this led researchers to think for the first time about the impact of chatbots on their users (Weizenbaum, 1976). The effect now carries the program's name. The Eliza effect is the tendency to unconsciously assume that computer behaviors are analogous to human behaviors. Douglas Hofstadter defines its specific form as our susceptibility to read far more understanding than is warranted into strings of symbols strung together by computers (Hofstadter, 1995). The standard illustration is not a chatbot at all but a cash machine that prints THANK YOU at the end of a transaction, which a naive observer might take for real gratitude. ELIZA exploited the same reflex at conversational scale: because it echoed your own words, every reply seemed relevant, and relevance felt like understanding.

رغم بساطة القواعد، يذكر SLP3 أن كثيرًا ممن تحدثوا مع ELIZA صاروا يعتقدون أنه يفهمهم فعلًا، وأن هذا دفع الباحثين إلى التفكير لأول مرة في أثر روبوتات المحادثة على مستخدميها (Weizenbaum, 1976). وصار الأثر يحمل اسم البرنامج. فـ Eliza effect هو الميل اللاواعي إلى افتراض أن سلوك الحاسوب مماثل لسلوك البشر. ويعرّف Douglas Hofstadter شكله الخاص بأنه قابليتنا لأن نقرأ فهمًا أكبر بكثير مما يُبرَّر في سلاسل رموز صفّها الحاسوب بعضها بجانب بعض (Hofstadter, 1995). والمثال المعتاد ليس روبوت محادثة أصلًا، بل جهاز صرف آلي يطبع THANK YOU في نهاية العملية، قد يظنه مراقب ساذج امتنانًا حقيقيًا. استغل ELIZA الردّ الغريزي نفسه على مستوى المحادثة: لأنه يردد كلماتك أنت، بدا كل رد في محله، والملاءمة بدت فهمًا.

What regex is for in an NLP pipelineما فائدة regex في خط معالجة NLP

A regular expression is fast, flexible pattern matching for text. It needs no training data, and it is precise in a way a learned model cannot be: a pattern either matches or it does not, and you can read off why. The slide lists four jobs, and it is worth having a concrete example ready for each.

التعبير النمطي (regular expression) مطابقة أنماط سريعة ومرنة للنصوص. لا يحتاج إلى بيانات تدريب، وهو دقيق بطريقة لا يقدر عليها نموذج متعلَّم: النمط إما أن يطابق أو لا يطابق، وتستطيع أن تقرأ السبب مباشرة. تسرد الشريحة أربع مهام، ومن المفيد أن يكون لديك مثال ملموس جاهز لكل منها.

Four jobs regex does in NLP (slide 57), with an example eachأربع مهام يؤديها الـ regex في NLP (الشريحة 57)، مع مثال لكل منها

Tokenization and pre-tokenizationالتقطيع والتقطيع المسبق
Split text into words, numbers and punctuation before a BPE tokenizer merges inside each piece. The GPT-2 pre-tokenizer in the next part is one regex.قسّم النص إلى كلمات وأرقام وعلامات ترقيم قبل أن يدمج BPE tokenizer داخل كل قطعة. الـ pre-tokenizer الخاص بـ GPT-2 في الجزء التالي هو regex واحد.
Normalizationالتوحيد
Recognize dates and numbers in any of their surface forms and rewrite them to one canonical form, such as dd-mm-yyyy.تعرّف على التواريخ والأرقام في أي صيغة ظاهرة لها، وأعد كتابتها بصيغة قياسية واحدة، مثل dd-mm-yyyy.
Filtering and cleaningالترشيح والتنظيف
Drop lines that are all punctuation, strip HTML tags, remove boilerplate, detect a script you do not want in a training corpus.احذف الأسطر المكوّنة كلها من علامات ترقيم، وانزع وسوم HTML، وأزل النصوص القالبية المكررة (boilerplate)، واكتشف نظام كتابة لا تريده في مدوّنة التدريب.
Feature extractionاستخراج السمات
Does the token contain a digit, start with a capital, end in -ing? Each answer is a binary feature a classifier can use.هل تحتوي الوحدة (token) على رقم، أو تبدأ بحرف كبير، أو تنتهي بـ -ing؟ كل إجابة سمة ثنائية يستطيع المصنِّف استخدامها.

The slide's last line matters more than it looks: regex is language- and task-dependent. A class like [a-z] says nothing about Arabic letters. A word boundary \b assumes words are made of letters, digits and underscores separated by something else, which fails outright for Chinese, where there are no spaces, and quietly misbehaves for Arabic under an ASCII-only definition of "letter". Recall the typology in part 04: an isolating language and a templatic one need different patterns for the same task, and a pattern tuned for tweets will not fit legal text. Regex gives you precision; it does not give you generality for free.

السطر الأخير في الشريحة أهم مما يبدو: الـ regex يعتمد على اللغة وعلى المهمة. فئة مثل [a-z] لا تقول شيئًا عن الحروف العربية. وword boundary (حد الكلمة) \b يفترض أن الكلمات مكوّنة من حروف وأرقام وشرطات سفلية يفصل بينها شيء آخر، وهذا يفشل تمامًا في الصينية حيث لا مسافات، ويسيء التصرف بصمت في العربية إذا كان تعريف «الحرف» مقصورًا على ASCII. تذكّر التصنيف اللغوي في الجزء 04: اللغة العازلة (isolating) واللغة القالبية (templatic) تحتاجان إلى أنماط مختلفة للمهمة نفسها، والنمط المضبوط للتغريدات لن يناسب النصوص القانونية. الـ regex يمنحك الدقة، لكنه لا يمنحك العمومية مجانًا.

Quick checkاختبار سريع

Which mechanism produced ELIZA's reply YOUR FATHER from the input My father?أي آلية أنتجت رد ELIZA وهو YOUR FATHER على المُدخل My father؟

Recall

Why did ELIZA convince people, in two sentences: one about the program and one about the people?لماذا أقنع ELIZA الناس؟ أجب بجملتين: واحدة عن البرنامج وواحدة عن الناس.

The program: keyword-triggered decomposition and reassembly rules with pronoun swapping echo the user's own words back, so every reply is on topic. The people: the Eliza effect, our tendency to read understanding into any behavior that looks conversational.
البرنامج: قواعد تفكيك وإعادة تركيب تطلقها كلمات مفتاحية، مع تبديل الضمائر، تعيد كلمات المستخدم نفسها إليه، فيأتي كل رد في صلب الموضوع. الناس: Eliza effect، أي ميلنا إلى قراءة الفهم في أي سلوك يبدو حواريًا.

Start with the simplest pattern there is. The regex Buttercup matches the substring Buttercup in "I'm called little Buttercup" and nowhere else (SLP3, section 2.6.1). Each letter is a literal that matches itself, and writing letters one after another means "this, then this, then this". That is concatenation, and abc matches exactly the three characters abc in that order.

ابدأ بأبسط نمط ممكن. الـ regex Buttercup يطابق السلسلة الجزئية Buttercup في «I'm called little Buttercup» ولا يطابق في أي مكان آخر (SLP3, section 2.6.1). كل حرف هنا حرف حرفي (literal) يطابق نفسه، وكتابة الحروف واحدًا بعد آخر تعني «هذا، ثم هذا، ثم هذا». هذا هو التسلسل (concatenation)، وabc يطابق الحروف الثلاثة abc بهذا الترتيب بالضبط.

Two more operators complete the algebra on slide 58. The vertical bar is disjunction: a|b matches either a or b. Parentheses group and define scope, so gupp(y|ies) matches guppy or guppies, while guppy|ies would match guppy or the bare string ies, because the bar has the lowest precedence of all and splits the whole pattern into two halves (SLP3, section 2.6.4). Regex is case sensitive throughout: s does not match S. Concatenation, disjunction and the Kleene star, which the next concept introduces, are the three operations that define regular languages in theory of computation. Parentheses only set scope, and classes, ranges, +, ? and counted repetition are all shorthand built from those three.

عاملان آخران يكملان الجبر في الشريحة 58. الخط العمودي هو الاختيار (disjunction): a|b يطابق a أو b. والأقواس تجمّع وتحدد النطاق، فـ gupp(y|ies) يطابق guppy أو guppies، بينما guppy|ies يطابق guppy أو السلسلة المجردة ies، لأن الخط العمودي له أدنى precedence (أولوية) على الإطلاق فيقسم النمط كله إلى نصفين (SLP3, section 2.6.4). والـ regex حساس لحالة الأحرف في كل مكان: s لا يطابق S. التسلسل والاختيار ونجمة Kleene، التي يقدمها المفهوم التالي، هي العمليات الثلاث التي تعرّف اللغات النظامية (regular languages) في نظرية الحوسبة. الأقواس تحدد النطاق فقط، أما الفئات والنطاقات و+ و? والتكرار المعدود فكلها اختصارات مبنية من تلك العمليات الثلاث.

The square-bracket classفئة الأقواس المربعة

Disjunction between single characters is so common that it has its own notation. A Character class in square brackets matches exactly one character from the set it lists. This is the fix for case sensitivity: [mM]ary matches Mary or mary. Read every row of the next three tables as the slides present them, pattern, meaning, and the first match marked in the example string.

الاختيار بين حروف مفردة شائع جدًا لدرجة أن له ترميزًا خاصًا. الـ character class (فئة الحروف) بين أقواس مربعة تطابق حرفًا واحدًا بالضبط من المجموعة التي تسردها. وهذا هو حل مشكلة حساسية حالة الأحرف: [mM]ary يطابق Mary أو mary. اقرأ كل صف في الجداول الثلاثة التالية كما تعرضه الشرائح: النمط، ومعناه، والمطابقة الأولى معلَّمة في نص المثال.

PatternالنمطMatchesيطابقFirst match in the exampleالمطابقة الأولى في المثال
[mM]ary[mM]aryMary or maryMary أو maryMary Ann stopped by Mona'sMary Ann stopped by Mona's
[abc][abc]a, b or ca أو b أو cIn uomini, in soldatiIn uomini, in soldati
[1234567890][1234567890]Any digitأي رقمplenty of 7 to 5plenty of 7 to 5
Slide 59: bracket disjunction (SLP3 Fig 2.8). The marked span is the first match.الشريحة 59: الاختيار بالأقواس (SLP3 Fig 2.8). المدى المعلَّم هو المطابقة الأولى.

Look closely at the second row. "In uomini" contains no a, b or c, so the first match is the a in soldati, eighteen characters in. A class matches one character, so a bracket never matches "abc" as a word; SLP3 asks why [catdog] does not mean cat or dog, and the answer is the same: it is one character drawn from c, a, t, d, o, g. Listing every digit is tedious, so a dash inside brackets gives a range in code point order: [0-9], [a-z], [A-Z], but also [2-5] or [b-g].

انظر جيدًا إلى الصف الثاني. «In uomini» لا يحتوي على a ولا b ولا c، فتكون المطابقة الأولى هي a في soldati، بعد ثمانية عشر حرفًا. الفئة تطابق حرفًا واحدًا، لذلك لا تطابق الأقواس أبدًا «abc» ككلمة. ويسأل SLP3 لماذا لا يعني [catdog] «cat أو dog»، والجواب نفسه: إنه حرف واحد مأخوذ من c, a, t, d, o, g. سرد كل الأرقام ممل، لذلك تعطي الشرطة داخل الأقواس نطاقًا (range) بترتيب نقاط الترميز (code point): [0-9] و[a-z] و[A-Z]، وأيضًا [2-5] أو [b-g].

PatternالنمطMatchesيطابقFirst match in the exampleالمطابقة الأولى في المثال
[A-Z][A-Z]An upper case letterحرف كبيرwe should call it 'Drenched Blossoms'we should call it 'Drenched Blossoms'
[a-z][a-z]A lower case letterحرف صغيرmy beans were impatient to be hoed!my beans were impatient to be hoed!
[0-9][0-9]A single digitرقم واحدChapter 1: Down the Rabbit HoleChapter 1: Down the Rabbit Hole
Slide 60: ranges with a dash (SLP3 Fig 2.9)الشريحة 60: النطاقات بالشرطة (SLP3 Fig 2.9)

The caret is the last bracket operator, and it is the one that trips people. When the caret is the first character inside brackets, the class is negated and matches any single character not in the set. Anywhere else inside brackets it is an ordinary caret. Python's documentation states both halves: the caret "has no special meaning if it's not the first character in the set", and [^^] matches any character except a caret.

علامة الإقحام ^ (caret) هي آخر عوامل الأقواس، وهي التي يتعثر فيها الناس. حين تكون ^ أول حرف داخل الأقواس، تُنفى الفئة وتطابق أي حرف واحد ليس في المجموعة. وفي أي موضع آخر داخل الأقواس هي حرف ^ عادي. وتوثيق Python يذكر النصفين: العلامة ^ «ليس لها معنى خاص إذا لم تكن الحرف الأول في المجموعة»، و[^^] يطابق أي حرف عدا ^.

PatternالنمطMatchesيطابقFirst match in the exampleالمطابقة الأولى في المثال
[^A-Z][^A-Z]Not an upper case letterليس حرفًا كبيرًاOyfn pripetchikOyfn pripetchik
[^Ss][^Ss]Neither S nor sلا S ولا sI have no exquisite reason for'tI have no exquisite reason for't
[^.][^.]Not a periodليس نقطةour resident Djinnour resident Djinn
[e^][e^]Either e or a carete أو علامة ^look up ^ nowlook up ^ now
a^ba^bThe pattern a^b, as the slide claimsالنمط a^b، كما تدّعي الشريحةlook up a^b now (no match)look up a^b now (no match)
a\^ba\^bThe literal string a^b, escapedالسلسلة الحرفية a^b، مهروبةlook up a^b nowlook up a^b now
Slide 61: caret inside brackets (SLP3 Fig 2.10)الشريحة 61: علامة ^ داخل الأقواس (SLP3 Fig 2.10)
Three faces of one symbol: an anchor at the line start outside brackets, a negating gate when first inside brackets, a plain character elsewhere inside brackets.ثلاثة وجوه لرمز واحد: مرساة عند بداية السطر خارج الأقواس، وبوابة نفي حين تأتي أولًا داخل الأقواس، وحرف عادي في غير ذلك داخل الأقواس.

Notice also that the third row needed no backslash. Inside brackets, special characters other than the backslash lose their special meaning; the Python documentation gives [(+*)] as a class that matches any of the literal characters (, +, * and ). So [^.] means "not a period" with a plain period, while outside brackets a bare period is the wildcard from the next concept and a literal period must be written \.. The two contexts have different grammars, and reading a pattern means always knowing which one you are in.

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

Quick checkاختبار سريع

Where must a caret sit to negate a bracket character class?أين يجب أن توضع علامة ^ كي تنفي فئة حروف بين أقواس؟

Recall

Why does [^.] need no backslash while a bare . outside brackets matches any character?لماذا لا تحتاج [^.] إلى شرطة مائلة عكسية، بينما النقطة المجردة خارج الأقواس تطابق أي حرف؟

Inside brackets special characters except the backslash lose their meaning, so the period is literal and the class means "not a period". Outside brackets the period is the wildcard, so a literal one must be written \..
داخل الأقواس تفقد الحروف الخاصة معناها عدا الشرطة المائلة العكسية، فتكون النقطة حرفية وتعني الفئة «ليس نقطة». خارج الأقواس النقطة هي الرمز الشامل، لذلك يجب أن تُكتب النقطة الحرفية \..

British and American spelling give the cleanest first example. You want one regex for color and colour. The u is optional, and colou?r says exactly that: the question mark makes the character before it appear zero or one times (SLP3, section 2.6.2). The same trick covers a plural: koalas?.

التهجئة البريطانية والأمريكية تعطي أوضح مثال أول. تريد regex واحدًا لـ color وcolour. حرف u اختياري، وcolou?r يقول ذلك بالضبط: علامة الاستفهام تجعل الحرف الذي قبلها يظهر صفر مرة أو مرة واحدة (SLP3, section 2.6.2). والحيلة نفسها تغطي الجمع: koalas?.

Now try sheep. Their language is baa!, baaa!, baaaa!, any number of a's of at least two. The Kleene star gives zero or more of the previous element, so baaa*! works: two literal a's, then any number more. The Kleene plus gives one or more, so baa+! says the same thing more readably. Both reject b!. Note what ba*! would do: with zero a's allowed, it accepts b!, which no sheep says. This is the recurring hazard of the star: it also matches nothing.

جرّب الآن الخراف. لغتها baa! وbaaa! وbaaaa!، أي عدد من حروف a لا يقل عن اثنين. نجمة Kleene تعطي صفرًا أو أكثر من العنصر السابق، لذلك يعمل baaa*!: حرفا a حرفيان، ثم أي عدد إضافي. وزائد Kleene يعطي واحدًا أو أكثر، فيقول baa+! الشيء نفسه بوضوح أكبر. وكلاهما يرفض b!. لاحظ ماذا كان سيفعل ba*!: بما أنه يسمح بصفر من a، فهو يقبل b!، وهذا ما لا يقوله أي خروف. هذا هو الخطر المتكرر في النجمة: إنها تطابق اللاشيء أيضًا.

Quantifiers and the wildcard (slides 62 and 63, SLP3 Fig 2.11)المكمِّمات والرمز الشامل (الشريحتان 62 و63، SLP3 Fig 2.11)

*
Zero or more occurrences of the previous character or expression. baa* matches ba, baa, baaa and so on.صفر أو أكثر من تكرارات الحرف أو التعبير السابق. baa* يطابق ba وbaa وbaaa وهكذا.
+
One or more occurrences. baa+ requires at least one a after the first, so it rejects ba.تكرار واحد أو أكثر. baa+ يشترط حرف a واحدًا على الأقل بعد الأول، لذلك يرفض ba.
?
Zero or one occurrence, meaning optional. colou?r matches both color and colour.صفر أو تكرار واحد، أي أن العنصر اختياري. colou?r يطابق color وcolour كليهما.
{n}
Exactly n occurrences. a{3} matches aaa and nothing shorter or longer.n تكرار بالضبط. a{3} يطابق aaa ولا شيء أقصر أو أطول.
{m,n}
Between m and n occurrences, inclusive. a{2,4} accepts aa, aaa and aaaa.بين m وn تكرار، شاملًا الحدين. a{2,4} يقبل aa وaaa وaaaa.
{m,} and {,n}{m,} و {,n}
At least m, or at most n. Omitting m sets a lower bound of zero and omitting n sets no upper bound (Python re documentation). JavaScript, and so the tester below, needs {0,n}: a bare {,n} is treated as literal text.m على الأقل، أو n على الأكثر. حذف m يجعل الحد الأدنى صفرًا، وحذف n يلغي الحد الأعلى (توثيق Python re). أما JavaScript، ومعها أداة الاختبار أدناه، فتحتاج إلى {0,n}: الصيغة المجردة {,n} تُعامَل كنص حرفي.
.
Any single character except a newline in most flavors.أي حرف واحد عدا السطر الجديد في معظم النسخ (flavors).
.*
Any string of zero or more characters: the wildcard under the star.أي سلسلة من صفر حرف أو أكثر: الرمز الشامل تحت النجمة.

A Quantifier applies to whatever is immediately before it: one character, one class, or one parenthesized group. So [0-9]+ is an integer of one or more digits, and on "Chapter 12 of 3" it finds 12 at 8 and 3 at 14. SLP3 asks why not [0-9]*, and the sheep already answered: the star matches the empty string, so [0-9]* would "match" at every position of a text with no digits at all. Reach for + whenever at least one is required.

الـ quantifier (المكمِّم) ينطبق على ما يسبقه مباشرة: حرف واحد، أو فئة واحدة، أو مجموعة واحدة بين أقواس. إذن [0-9]+ عدد صحيح من رقم واحد أو أكثر، وعلى «Chapter 12 of 3» يجد 12 عند 8 و3 عند 14. ويسأل SLP3 لماذا لا نستخدم [0-9]*، والخراف أجابت بالفعل: النجمة تطابق السلسلة الفارغة، فـ [0-9]* كان «سيطابق» عند كل موضع في نص لا أرقام فيه إطلاقًا. استخدم + كلما كان المطلوب واحدًا على الأقل.

The wildcardالرمز الشامل

The period matches any single character. In Python's default mode that is any character except a newline, and the DOTALL flag lifts the exception; in JavaScript the dot excludes the line terminators and the s flag lifts it (Python re documentation; MDN). Under a star it becomes the most powerful and most dangerous idiom in the language: .* is any string of zero or more characters. a.*b is an a, then anything, then a b, and rose.*rose finds two roses with anything between.

النقطة تطابق أي حرف واحد. في الوضع الافتراضي لـ Python هذا يعني أي حرف عدا السطر الجديد، والعلَم DOTALL يرفع هذا الاستثناء. وفي JavaScript تستثني النقطة فواصل الأسطر، والعلَم s يرفع ذلك (توثيق Python re، وMDN). وتحت النجمة تصبح أقوى عبارة في اللغة وأخطرها: .* أي سلسلة من صفر حرف أو أكثر. a.*b هو a ثم أي شيء ثم b، وrose.*rose يجد كلمتي rose بينهما أي شيء.

Greedy versus lazyالجشع مقابل الكسول

Here is the question that decides whether .* does what you meant. Run <.*> on the string <a><b>. You probably wanted the first tag. You get the whole string, because regular expressions always match the largest string they can; SLP3 says the patterns are greedy. The star grabs everything up to the end and then backs off only as far as needed for the final > to match, which is the last one. Adding a question mark after a quantifier makes it lazy: *? and +? match as little as possible, expanding only when the rest of the pattern cannot otherwise succeed (MDN, Python re documentation).

هذا هو السؤال الذي يحدد هل يفعل .* ما قصدته. شغّل <.*> على السلسلة <a><b>. على الأرجح أردت الوسم الأول، لكنك تحصل على السلسلة كلها، لأن التعابير النمطية تطابق دائمًا أطول سلسلة ممكنة، ويقول SLP3 إن الأنماط greedy (جشعة). النجمة تأخذ كل شيء حتى النهاية ثم تتراجع فقط بالقدر اللازم كي تطابق > الأخيرة في النمط، وهي آخر > في النص. وإضافة علامة استفهام بعد المكمِّم تجعله كسولًا (lazy): *? و+? تطابقان أقل قدر ممكن، ولا تتوسعان إلا حين لا يستطيع باقي النمط أن ينجح بغير ذلك (MDN، توثيق Python re).

On <a><b>, the greedy <.*> sweeps across both tags in one match; the lazy <.*?> stops at the first closing bracket and then finds <b> as a second match.على <a><b>، يكتسح النمط الجشع <.*> الوسمين معًا في مطابقة واحدة، أما النمط الكسول <.*?> فيتوقف عند أول قوس إغلاق ثم يجد <b> كمطابقة ثانية.
PatternالنمطStringالسلسلةMatchesالمطابقاتLength of first matchطول المطابقة الأولى
<.*><.*><a><b><a><b>one match, <a><b> at 0مطابقة واحدة، <a><b> عند 066
<.*?><.*?><a><b><a><b>two matches, <a> at 0 and <b> at 3مطابقتان، <a> عند 0 و<b> عند 333
a.*ba.*bxaxbxbxxaxbxbxone match, axbxb at 1مطابقة واحدة، axbxb عند 155
a.*?ba.*?bxaxbxbxxaxbxbxone match, axb at 1مطابقة واحدة، axb عند 133
Greedy and lazy on the same strings, computed with the JavaScript engineالجشع والكسول على السلاسل نفسها، محسوبة بمحرك JavaScript

Worked exampleمثال محلول

Predicting a.*b against a.*?b on xaxbxbxالتنبؤ بنتيجة a.*b مقابل a.*?b على xaxbxbx

  1. Find where a match can startحدّد أين يمكن أن تبدأ المطابقة

    The only a is at index 1, so both patterns start there.
    حرف a الوحيد عند الموضع 1، لذلك يبدأ النمطان كلاهما من هناك.
  2. Greedyالجشع

    .* takes everything to the end, xbxbx, then gives back one character at a time until a b can match. The last b is at index 5, so the match is axbxb, indices 1 to 5.
    .* يأخذ كل شيء حتى النهاية، xbxbx، ثم يعيد حرفًا واحدًا في كل مرة حتى يمكن أن يطابق b. آخر b عند الموضع 5، فتكون المطابقة axbxb، من الموضع 1 إلى 5.
  3. Lazyالكسول

    .*? starts by taking nothing and tries b at index 2; it is an x, so the star extends by one. Now b at index 3 matches. The match is axb, indices 1 to 3.
    .*? يبدأ بأخذ لا شيء ويجرب b عند الموضع 2، فيجده x، فتمتد النجمة بحرف واحد. الآن b عند الموضع 3 يطابق. المطابقة هي axb، من الموضع 1 إلى 3.
  4. Resultالنتيجة

    Greedy: axbxb (5 characters). Lazy: axb (3 characters). Same start, different end.
    الجشع: axbxb (5 أحرف). الكسول: axb (3 أحرف). البداية نفسها، والنهاية مختلفة.

Quick checkاختبار سريع

Which span does the lazy pattern a.*?b match first inside the string xaxbxbx?ما المدى الذي يطابقه النمط الكسول a.*?b أولًا داخل السلسلة xaxbxbx؟

Quick checkاختبار سريع

What does the star quantifier require of the element before it?ماذا يشترط مكمِّم النجمة على العنصر الذي قبله؟

Recall

Predict the first match of a.*b and of a.*?b on the string xaxbxbx, with indices.تنبأ بالمطابقة الأولى لكل من a.*b و a.*?b على السلسلة xaxbxbx، مع المواضع.

Greedy a.*b gives axbxb, indices 1 to 5. Lazy a.*?b gives axb, indices 1 to 3.
الجشع a.*b يعطي axbxb، من الموضع 1 إلى 5. والكسول a.*?b يعطي axb، من الموضع 1 إلى 3.

Everything so far matched characters. The last two regex tools match positions. ^The matches The only at the start of a line, $ finds a trailing space at the end of one, and ^The dog\.$ matches a line that is exactly "The dog." and nothing else (SLP3, section 2.6.3).

كل ما سبق كان يطابق حروفًا. أما آخر أداتين في الـ regex فتطابقان مواضع. ^The يطابق The فقط في بداية السطر، و $ يجد مسافة زائدة في نهاية السطر، و^The dog\.$ يطابق سطرًا هو «The dog.» بالضبط ولا شيء غيره (SLP3, section 2.6.3).

These are anchors, and the crucial property is that they consume nothing. An anchor matches the empty string at a position that satisfies a condition, so the\b the can match "the the": the boundary sits between the e and the space without using up either. In Python, ^ matches the start of the string, and in MULTILINE mode also immediately after each newline; $ matches the end of the string or just before the final newline, and in MULTILINE mode before every newline (Python re documentation). JavaScript's m flag does the same job, which is why the tester below has one.

هذه هي anchors (المراسي)، وخاصيتها الحاسمة أنها لا تستهلك شيئًا. المرساة تطابق السلسلة الفارغة عند موضع يحقق شرطًا، لذلك يمكن لـ the\b the أن يطابق «the the»: الحد يقع بين e والمسافة دون أن يستهلك أيًا منهما. في Python تطابق ^ بداية السلسلة، وفي وضع MULTILINE تطابق أيضًا مباشرة بعد كل سطر جديد. وتطابق $ نهاية السلسلة أو ما قبل السطر الجديد الأخير مباشرة، وفي وضع MULTILINE تطابق قبل كل سطر جديد (توثيق Python re). والعلَم m في JavaScript يؤدي المهمة نفسها، ولهذا يوجد في أداة الاختبار أدناه.

That is what "line-based formats" on the slide means in practice: real files are one record per line, and the multiline flag turns ^ and $ into per-line assertions. A comments filter on a corpus file, and a date extractor on a log, are the same pattern shape.

هذا ما تعنيه عبارة «الصيغ القائمة على الأسطر» (line-based formats) في الشريحة عمليًا: الملفات الحقيقية سجل واحد في كل سطر، والعلَم متعدد الأسطر يحوّل ^ و$ إلى شروط على مستوى كل سطر. مرشّح التعليقات على ملف مدوّنة، ومستخرج التواريخ من سجل (log)، لهما شكل النمط نفسه.

PatternالنمطText (one record per line)النص (سجل واحد في كل سطر)Matches with mالمطابقات مع mMatches without mالمطابقات بدون m
^#.*$^#.*$# comment, text line, # another# comment، text line، # another2 matches: # comment and # another, each at the start of its line2 مطابقتان: # comment و# another، كل منهما في بداية سطرها00
^\d{4}-\d{2}-\d{2}^\d{4}-\d{2}-\d{2}2026-09-16 boot, user logged in, 2026-09-17 shutdown2026-09-16 boot، user logged in، 2026-09-17 shutdown2 matches: the timestamps opening lines 1 and 32 مطابقتان: الطابعان الزمنيان في بداية السطرين 1 و311
Line-based formats under the m flag, computed with the JavaScript engineالصيغ القائمة على الأسطر مع العلَم m، محسوبة بمحرك JavaScript

Without the flag, ^ sees only the start of the whole string, so the comments filter finds nothing and the date pattern catches only a first line that happens to begin with a timestamp. With the flag, each newline resets ^ and $, which is exactly how you scan a log or strip comment lines from a file. Flip the m flag on the ^The preset in the tester below to feel the difference.

بدون العلَم، لا ترى ^ إلا بداية السلسلة كلها، فلا يجد مرشّح التعليقات شيئًا، ولا يلتقط نمط التاريخ إلا سطرًا أول يصادف أنه يبدأ بطابع زمني. ومع العلَم، كل سطر جديد يعيد ضبط ^ و$، وهذا بالضبط ما تفعله حين تمسح سجلًا أو تحذف أسطر التعليقات من ملف. بدّل العلَم m على المثال الجاهز ^The في أداة الاختبار أدناه لتشعر بالفرق.

AnchorالمرساةPosition it assertsالموضع الذي تشترطهExampleمثال
^^Start of the string, or of a line with the multiline flagبداية السلسلة، أو بداية السطر مع العلَم متعدد الأسطر^The finds The at index 0 of "The dog"^The يجد The عند الموضع 0 في «The dog»
$$End of the string, or of a line with the multiline flagنهاية السلسلة، أو نهاية السطر مع العلَم متعدد الأسطر\.$ finds the period at index 7 of "The dog."\.$ يجد النقطة عند الموضع 7 في «The dog.»
\b\bBetween a word character and a non-word character, or a string edgeبين حرف كلمة وحرف ليس من حروف الكلمة، أو عند طرف السلسلة\bthe\b finds the at index 0 of "the other theme"\bthe\b يجد the عند الموضع 0 في «the other theme»
\B\BAny position that is not a word boundaryأي موضع ليس حد كلمة\Bthe finds the inside other\Bthe يجد the داخل other
Anchors (slide 64)المراسي (الشريحة 64)

The word boundaryحد الكلمة

The slide says \b is useful for matching whole words, and the canonical example is the word "the". Plain the also matches inside other and theme. \bthe\b requires a boundary on each side, so on "the other theme" it lights only the first word. A word character is a letter, a digit or an underscore, and the boundary is the seam between such a character and anything else, or a string edge (Python re documentation). Python's own examples make the rule vivid: r'\bat\b' matches at, at., (at) and the at in "as at ay", but not attempt or atlas.

تقول الشريحة إن \b مفيد لمطابقة الكلمات الكاملة، والمثال الكلاسيكي هو الكلمة «the». النمط المجرد the يطابق أيضًا داخل other وtheme. أما \bthe\b فيشترط boundary (حدًا) على كل جانب، فعلى «the other theme» لا يضيء إلا الكلمة الأولى. حرف الكلمة (word character) هو حرف أبجدي أو رقم أو شرطة سفلية، والحد هو الفاصل بين حرف كهذا وأي شيء آخر، أو طرف السلسلة (توثيق Python re). وأمثلة Python نفسها توضح القاعدة: r'\bat\b' يطابق at وat. و(at) وat في «as at ay»، لكنه لا يطابق attempt ولا atlas.

Ticks mark every word boundary in the string. \bthe\b lights only the standalone the. The the inside other has letters on both sides, and the the that opens theme has a boundary on its left but an m after its e, so \bthe\b fails at both.العلامات تحدد كل حد كلمة في السلسلة. \bthe\b يضيء فقط the المستقلة. أما the داخل other فحولها حروف من الجانبين، و the التي تبدأ بها theme لها حد على يسارها لكن بعد e يأتي m، لذلك يفشل \bthe\b في الموضعين.

Digits count as word characters too, which produces the example SLP3 uses to check that you have understood the definition rather than memorized "letters". \b99\b matches in "There are 99 bottles" and in "$99", because a dollar sign is not a word character, but not in "299", because the 2 is. On "There are 299 bottles, $99 each" it finds exactly one match, the 99 at index 24.

الأرقام تُعدّ حروف كلمة أيضًا، ومن هنا يأتي المثال الذي يستخدمه SLP3 ليتحقق أنك فهمت التعريف بدل أن تحفظ «حروفًا أبجدية». \b99\b يطابق في «There are 99 bottles» وفي «$99»، لأن علامة الدولار ليست حرف كلمة، لكنه لا يطابق في «299»، لأن 2 حرف كلمة. وعلى «There are 299 bottles, $99 each» يجد مطابقة واحدة بالضبط، هي 99 عند الموضع 24.

SLP3 tells the story of the word "the" as a precision and recall exercise. the misses The at the start of a sentence, a false negative, so you write [tT]he. Now it hits other and there, false positives, so you write \b[tT]he\b. Every regex you write for a real corpus goes through the same two-sided tuning, and the boundary is usually the second fix.

يروي SLP3 قصة الكلمة «the» كتمرين في الدقة (precision) والاستدعاء (recall). النمط the يفوّت The في بداية الجملة، وهذا سلبي كاذب (false negative)، فتكتب [tT]he. الآن يصيب other وthere، وهذه إيجابيات كاذبة (false positives)، فتكتب \b[tT]he\b. كل regex تكتبه لمدوّنة حقيقية يمر بهذا الضبط نفسه من الجهتين، والحد عادةً هو الإصلاح الثاني.

The six aliasesالاختصارات الستة

Some classes are needed so often that they get a backslash shorthand. Slide 65 lists six, in three complementary pairs. Each lower case alias is a class, and its upper case partner is the negation of that class.

بعض الفئات نحتاجها كثيرًا لدرجة أنها تحصل على اختصار بشرطة مائلة عكسية. تسرد الشريحة 65 ستة منها، في ثلاثة أزواج متتامة. كل اختصار بحرف صغير فئة، وشريكه بحرف كبير هو نفي تلك الفئة.

AliasالاختصارExpansionالتوسعةMatchesيطابقFirst match in the exampleالمطابقة الأولى في المثال
\d\d[0-9][0-9]Any digitأي رقمParty of 5Party of 5
\D\D[^0-9][^0-9]Any non-digitأي حرف ليس رقمًاBlue moonBlue moon
\w\w[a-zA-Z0-9_][a-zA-Z0-9_]Any alphanumeric or underscoreأي حرف أبجدي أو رقم أو شرطة سفليةDaiyuDaiyu
\W\W[^\w][^\w]A non-alphanumericحرف ليس أبجديًا ولا رقمًا!!!!!!!!
\s\s[ \r\t\n\f][ \r\t\n\f]Whitespace: space, tab, newlineمسافة بيضاء: مسافة، أو جدولة (tab)، أو سطر جديدin Concordin Concord
\S\S[^\s][^\s]Non-whitespaceليس مسافة بيضاءin Concordin Concord
Aliases (slide 65, SLP3 Fig 2.13), with the first match markedالاختصارات (الشريحة 65، SLP3 Fig 2.13)، مع تعليم المطابقة الأولى

The expansions in the table are the SLP3 definitions, and they are ASCII. Real engines differ at the edges, and the differences matter for Arabic. In Python 3, a pattern on a str treats \d as any Unicode decimal digit, including Arabic-Indic digits, \w as any Unicode alphanumeric plus the underscore, so Arabic letters count, and \s as anything str.isspace() accepts, which includes the non-breaking space; the ASCII flag switches all three back to the table above, with \s as [ \t\n\r\f\v] (Python re documentation). JavaScript keeps \w at letters, digits and underscore and \d at [0-9], while its \s covers all Unicode whitespace and line terminators (MDN). So a boundary such as \b, which is defined in terms of \w, falls in different places for the same Arabic sentence in the two languages. This is the "language-dependent" warning from slide 57 in its most practical form.

التوسعات في الجدول هي تعريفات SLP3، وهي ASCII. المحركات الحقيقية تختلف عند الأطراف، وهذه الفروق مهمة للعربية. في Python 3، النمط المطبَّق على str يعامل \d كأي رقم عشري في Unicode، بما فيها الأرقام العربية الهندية (٠١٢٣)، ويعامل \w كأي حرف أو رقم في Unicode مع الشرطة السفلية، فتُحسب الحروف العربية، ويعامل \s كأي شيء يقبله str.isspace()، بما فيه المسافة غير القابلة للكسر (non-breaking space). والعلَم ASCII يعيد الثلاثة إلى ما في الجدول أعلاه، مع \s بمعنى [ \t\n\r\f\v] (توثيق Python re). أما JavaScript فتُبقي \w على الحروف اللاتينية والأرقام والشرطة السفلية، و\d على [0-9]، بينما يغطي \s فيها كل مسافات Unicode وفواصل الأسطر (MDN). لذلك فإن حدًا مثل \b، المعرَّف بدلالة \w، يقع في أماكن مختلفة للجملة العربية نفسها في اللغتين. وهذا هو تحذير «الاعتماد على اللغة» من الشريحة 57 في أكثر صوره عملية.

A backslash works both waysالشرطة المائلة العكسية تعمل في الاتجاهين

Inside a pattern, a backslash before a special character makes it literal: \. is a period, \^ is a caret. The same backslash before an ordinary letter creates an alias such as \d or \b. The full table of escaped specials, from K\*A\*P\*L\*A\*N to the raw-string question, comes in the next part.

داخل النمط، الشرطة المائلة العكسية قبل حرف خاص تجعله حرفيًا: \. نقطة، و\^ علامة ^. والشرطة نفسها قبل حرف عادي تنشئ اختصارًا مثل \d أو \b. الجدول الكامل للحروف الخاصة المهروبة، من K\*A\*P\*L\*A\*N إلى سؤال السلاسل الخام (raw string)، يأتي في الجزء التالي.

Quick checkاختبار سريع

Which pattern matches the standalone word the but not other or theme?أي نمط يطابق الكلمة المستقلة the ولا يطابق other ولا theme؟

Quick checkاختبار سريع

Which alias expands to the class [a-zA-Z0-9_]?أي اختصار يتوسع إلى الفئة [a-zA-Z0-9_]؟

Recall

Expand \w and \s, and name their negations.وسّع \w و \s، وسمِّ نفي كل منهما.

\w is [a-zA-Z0-9_], negated by \W. \s is [ \r\t\n\f], negated by \S. Python adds \v and, for str patterns, every Unicode whitespace character.
\w هي [a-zA-Z0-9_]، ونفيها \W. و\s هي [ \r\t\n\f]، ونفيها \S. وتضيف Python الحرف \v، ولأنماط str كل حرف مسافة في Unicode.

Recall

What are the three meanings of the caret, and which one does Python or JavaScript apply to a caret outside brackets?ما المعاني الثلاثة للعلامة ^، وأيها تطبقه Python أو JavaScript على ^ خارج الأقواس؟

Start-of-line anchor outside brackets, negation when first inside brackets, a literal caret elsewhere inside brackets. Outside brackets both engines always read it as an anchor, so a literal caret there must be written \^.
مرساة بداية السطر خارج الأقواس، والنفي حين تأتي أولًا داخل الأقواس، و^ حرفية في أي موضع آخر داخل الأقواس. خارج الأقواس يقرؤها المحركان دائمًا كمرساة، لذلك يجب أن تُكتب ^ الحرفية هناك \^.

Recall

Write a regex for a word starting with a capital letter and say what each piece does.اكتب regex لكلمة تبدأ بحرف كبير، واشرح ما تفعله كل قطعة.

\b[A-Z][a-z]*: a word boundary so the match starts a word, one upper case letter, zero or more lower case letters. \b[A-Z]\w* also accepts digits and underscores in the rest of the word.
\b[A-Z][a-z]*: حد كلمة كي تبدأ المطابقة كلمة، ثم حرف كبير واحد، ثم صفر أو أكثر من الحروف الصغيرة. والنمط \b[A-Z]\w* يقبل أيضًا الأرقام والشرطات السفلية في باقي الكلمة.

Check every row yourselfتحقق من كل صف بنفسك

The tester below loads every example from slides 59 to 65, the greedy and lazy pairs, and the ELIZA rule with its captured group. Load a preset, read the first match, then edit the pattern and watch the highlight move. Try a^b to see the erratum with your own eyes, and switch the m flag off on the ^The preset to see anchors change meaning.

أداة الاختبار أدناه تحمّل كل مثال من الشرائح 59 إلى 65، وأزواج الجشع والكسول، وقاعدة ELIZA مع مجموعتها الملتقطة. حمّل مثالًا جاهزًا، واقرأ المطابقة الأولى، ثم عدّل النمط وراقب التظليل وهو يتحرك. جرّب a^b لترى الخطأ في الشريحة بعينيك، وأطفئ العلَم m على المثال الجاهز ^The لترى المراسي يتغير معناها.

InteractiveتفاعليRegex tester: every table row from the slides, run live in your browserمختبر Regex: كل صف من جداول الشرائح، يعمل مباشرةً في متصفحك
HE SAYS YOU ARE DEPRESSED MUCH OF THE TIME.
  1. Matchالتطابق 1at indexعند الموضع 0HE SAYS YOU ARE DEPRESSED MUCH OF THE TIME.$1 = DEPRESSED
Group 1 holds the word ELIZA copies into I AM SORRY TO HEAR YOU ARE \1.تحمل المجموعة 1 الكلمة التي ينسخها ELIZA في الرد I AM SORRY TO HEAR YOU ARE \1.
Matchesالتطابقات1with g
First matchأول تطابق0index43 characters longطوله 43 محارف
Groupsالمجموعات1capturednumbered $1, $2 in JavaScriptمرقّمة $1 و$2 في JavaScript

The tester runs the browser's JavaScript RegExp engine. Its \s and \d follow the ECMAScript definitions, and . excludes the four line terminators unless s is on, so a Python result can differ by a character in edge cases. Patterns that would match the empty string, such as a*, advance one character per empty match.يشغّل المختبر محرك RegExp الخاص بـJavaScript في المتصفح. يتبع \s و\d فيه تعريفات ECMAScript، ولا تطابق . محارف نهاية السطر الأربعة إلا إذا فُعِّل s، لذلك قد تختلف نتيجة Python بمحرف واحد في الحالات الطرفية. والأنماط التي قد تطابق سلسلة فارغة، مثل a*، تتقدم محرفًا واحدًا عند كل تطابق فارغ.

Recapالخلاصة

If you remember nothing elseإن لم تتذكر شيئاً آخر فتذكّر هذا

  • ELIZA is a cascade of keyword-triggered decomposition and reassembly rules: .* YOU ARE (DEPRESSED|SAD) .* becomes I AM SORRY TO HEAR YOU ARE \1. The Eliza effect names our habit of reading understanding into such echoes.ELIZA سلسلة من قواعد التفكيك (decomposition) وإعادة التركيب (reassembly) تطلقها كلمات مفتاحية: النمط .* YOU ARE (DEPRESSED|SAD) .* يصبح I AM SORRY TO HEAR YOU ARE \1. وظاهرة Eliza effect هي ميلنا إلى أن نقرأ فهمًا في مثل هذا الصدى.
  • NLP uses regex for tokenization and pre-tokenization, normalization of dates and numbers, filtering and cleaning, and feature extraction. Regex is language- and task-dependent.تستخدم NLP التعابير النمطية (regex) في التقطيع (tokenization) والتقطيع المسبق (pre-tokenization)، وفي توحيد صيغ التواريخ والأرقام (normalization)، وفي الترشيح والتنظيف، وفي استخراج السمات (feature extraction). والـ regex يعتمد على اللغة وعلى المهمة.
  • Literals match themselves, abc is concatenation, a|b is disjunction, parentheses set scope. [mM], [a-z] and [^0-9] each match exactly one character.الحروف الحرفية تطابق نفسها، و abc تسلسل، و a|b اختيار، والأقواس تحدد النطاق. كل من [mM] و [a-z] و [^0-9] يطابق حرفًا واحدًا بالضبط.
  • The caret has three faces: an anchor outside brackets, negation when first inside brackets, a literal elsewhere inside brackets. In Python and JavaScript a caret outside brackets is always an anchor, so a literal needs \^.للعلامة ^ ثلاثة وجوه: مرساة خارج الأقواس، ونفي إذا جاءت أولًا داخل الأقواس، وحرف عادي في أي موضع آخر داخل الأقواس. في Python و JavaScript تكون ^ خارج الأقواس مرساة دائمًا، لذلك يحتاج الحرف العادي إلى \^.
  • * is zero or more, + one or more, ? zero or one, {n} exactly n, {m,n} between m and n. The dot is any character except a newline, so .* is any string.* تعني صفرًا أو أكثر، و + واحدًا أو أكثر، و ? صفرًا أو واحدًا، و {n} عدد n بالضبط، و {m,n} بين m و n. والنقطة أي حرف عدا السطر الجديد، لذلك .* تعني أي سلسلة نصية.
  • Quantifiers are greedy. *? and +? are lazy: <.*> eats all of <a><b>, <.*?> stops at <a> and then finds <b>.المكمِّمات (quantifiers) جشعة. أما *? و +? فكسولة: <.*> يبتلع كامل <a><b>، بينما <.*?> يتوقف عند <a> ثم يجد <b>.
  • ^ and $ anchor line edges, \b is a zero-width word boundary. \bthe\b matches the but not other, and \b99\b matches in $99 but not in 299.^ و $ تثبّتان طرفي السطر، و \b حد كلمة عرضه صفر. النمط \bthe\b يطابق the ولا يطابق other، و \b99\b يطابق في $99 ولا يطابق في 299.
  • \d is [0-9], \D is [^0-9], \w is [a-zA-Z0-9_], \W is [^\w], \s is [ \r\t\n\f], \S is [^\s]. Escape a literal special character with a backslash.\d هي [0-9]، و \D هي [^0-9]، و \w هي [a-zA-Z0-9_]، و \W هي [^\w]، و \s هي [ \r\t\n\f]، و \S هي [^\s]. لمطابقة حرف خاص كما هو، اسبقه بشرطة مائلة عكسية.

Sourcesالمصادر