أنت تعرف الأساسيات بالفعل: أصناف المحارف مثل \d و[A-Z]، والمكمِّمات مثل {4} و+، والكلمات matches? وall-matching-subseqs وre-replace. يضيف هذا التمرين الأجزاء من التعبيرات النمطية التي تصف البنية والسياق. وهي توجد في نفس مفردات regexp، مكتوبةً بالصيغة الحرفية R/ / نفسها.
تطابق المراسي موضعًا لا محرفًا:
^ ! the start of the string
$ ! the end of the string
\b ! a word boundary
ولأن $ تعني نهاية السلسلة النصية، اكتب \$ عندما تقصد علامة الدولار الحرفية.
حد الكلمة (\b) هو الموضع الذي يلتقي فيه محرف الكلمة بمحرف ليس من محارف الكلمة. محارف الكلمة هي الحروف والأرقام والشرطة السفلية، وكل ما عدا ذلك (المسافات وعلامات الترقيم وطرفا السلسلة النصية) يُعدّ حدًا. لذا فإن \bcat\b تطابق cat فقط عندما تقف وحدها:
USING: regexp ;
"cat nap" R/ \bcat\b/ re-contains? . ! => t
"scatter" R/ \bcat\b/ re-contains? . ! => f (cat sits inside a word)
الأقواس الهلالية ( ) تجمع جزءًا من النمط كي ينطبق مكمِّم، أو | ("هذا أو ذاك")، على المجموعة بأكملها:
USING: regexp ;
"abab" R/ (ab)+/ matches? . ! => t (+ applies to "ab")
"dog" R/ cat|dog/ matches? . ! => t (either word)
"$100.50" R/ \$\d+(\.\d{2})?/ matches? . ! => t
"$100" R/ \$\d+(\.\d{2})?/ matches? . ! => t (the group is optional)
يُقرأ النمط الأخير كالتالي: "علامة دولار، ورقم واحد أو أكثر، ثم مجموعة اختيارية من نقطة ورقمين".
ملاحظة: في Factor، لا تفعل المجموعة سوى تنظيم النمط. وخلافًا لبعض أدوات التعبيرات النمطية، لا يمكنك استخراج النص الذي طابقته مجموعة (فلا يوجد استخلاص لمجموعة الالتقاط، ولا تُدعم الإحالات المرجعية مثل
\1). ولانتقاء نص حول علامة مميزة، استخدم النظر حول بدلًا من ذلك (بالأسفل).
يتحقق النظر حول مما يأتي قبل الموضع الحالي مباشرة أو بعده مباشرة دون أن يجعل تلك المحارف جزءًا من المطابقة. فهو "ذو عرض صفري": ما يختبره لا يدخل في النتيجة.
(?=...) ! lookahead: ... must follow
(?!...) ! negative lookahead: ... must NOT follow
(?<=...) ! lookbehind: ... must come before
(?<!...) ! negative lookbehind: ... must NOT come before
النظر حول انتقائي: المحارف نفسها قد تطابق أو لا تطابق حسب ما يجاورها. فالنمط \d+ المجرّد يلتقط كل رقم، أما النظر للخلف والنظر للأمام فيُبقيان فقط ما له الجار الصحيح:
USING: regexp ;
"3 for $10 or 10 for $30" R/ \d+/ all-matching-subseqs .
! => { "3" "10" "10" "30" } (every number)
"3 for $10 or 10 for $30" R/ (?<=\$)\d+/ all-matching-subseqs .
! => { "10" "30" } (only the prices — the bare 3 and 10 drop)
"buy 2 at 15% off, 4 at 30% off" R/ \d+(?=%)/ all-matching-subseqs .
! => { "15" "30" } (only the discounts — the bare 2 and 4 drop)
أضف حرفًا بعد / الختامي لتغيير سلوك النمط بأكمله. ويجعله i غير حساس لحالة الأحرف:
USING: regexp ;
"REFUND" R/ refund/i matches? . ! => t
"Refund" R/ refund/i matches? . ! => t
يمنحك all-matching-subseqs النص المطابَق. ويمضي map-matches خطوة أبعد، إذ يشغّل اقتباسًا على كل مطابقة ويجمع النتائج. يستقبل الاقتباس فهرس start للمطابقة وفهرس end والسلسلة النصية كاملة؛ ويحوّل subseq هذه الثلاثة إلى النص المطابَق، الذي تحوّله أنت بعد ذلك:
map-matches ( string regexp quot: ( start end string -- obj ) -- seq )
USING: math regexp sequences ;
"a1 b22 c333" R/ \d+/ [ subseq length ] map-matches .
! => { 1 2 3 } (the length of each run of digits)
أما each-match، نظيره الذي يقتصر على الآثار الجانبية، فيشغّل اقتباسًا على كل مطابقة دون جمع أي شيء.
أنت مسؤول عن دفاتر شركة صغيرة، وتصل معاملات كل يوم على هيئة أسطر نصية غير مرتبة. ستستخدم التعبيرات النمطية للتحقق من صحة المبالغ، واستخراج الأرقام عبر الرمز الذي يسبقها، ووضع علامة على الأسطر التي تحتاج إلى نظرة أدق.
المبلغ الصحيح البنية هو $ يتبعه رقم واحد أو أكثر، ثم جزء سنتات اختياري يتكوّن من نقطة تليها رقمان بالضبط: $100 أو $100.50، وليس $100.5. عرّف valid-amount?، بحيث تُرجع t عندما تكون السلسلة كاملةً مبلغًا صحيح البنية.
"$100.50" valid-amount? . ! => t
"$100" valid-amount? . ! => t
"$100.5" valid-amount? . ! => f
عرّف dollar-amounts، بحيث تُرجع كل عدد يلي $ مباشرةً في السطر، الأرقام فقط دون $، بالترتيب.
"spent $100 and $25 today" dollar-amounts .
! => { "100" "25" }
عرّف percentages، بحيث تُرجع كل عدد تليه % مباشرةً.
"up 5% then down 12%" percentages .
! => { "5" "12" }
عرّف flagged?، بحيث تُرجع t عندما يذكر السطر refund أو chargeback بأي مزيج من الحروف الكبيرة والصغيرة.
"Issued a REFUND today" flagged? . ! => t
"a normal sale" flagged? . ! => f
سجّل في Exercism لتتعلّم وتتقن Factor عبر 47 مفهومًا163 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.