الفرق بين المراجعتين لصفحة: «Ruby/Regexp»
لا ملخص تعديل |
لا ملخص تعديل |
||
(10 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة) | |||
سطر 1: | سطر 1: | ||
<noinclude>{{DISPLAYTITLE: | <noinclude>{{DISPLAYTITLE:الصنف <code>Regexp</code> في روبي}}</noinclude> | ||
[[تصنيف: Ruby]] | [[تصنيف: Ruby]] | ||
[[تصنيف: Ruby Class]] | |||
[[تصنيف: Ruby Regexp]] | [[تصنيف: Ruby Regexp]] | ||
كائنات الصنف <code>Regexp</code> التعابير | تمثل كائنات الصنف <code>Regexp</code> التعابير النمطية التي تُستخدم لمطابقة نمط (pattern) معيّن في [[Ruby/String|سلسلة نصية]]. تُنشَأ التعابير النمطية باستخدام الصياغتين <code>/.../</code> و <code>%r{...}</code>، أو باستعمال الباني <code>[[Ruby/Regexp/new|new]]</code>. | ||
التعابير النمطية هي أنماط تصف محتويات السلسلة النصية. يمكن استخدامها للتحقق من أنّ سلسلة نصية تحتوي على نمط معين، أو لاستخراج الأجزاء المُطابقة | التعابير النمطية هي أنماط تصف محتويات السلسلة النصية. يمكن استخدامها للتحقق من أنّ سلسلة نصية تحتوي على نمط معين، أو لاستخراج الأجزاء المُطابقة منها. | ||
عادةً ما يتم تحديد التعبير النمطي بخط مائل (/) كما يوضح المثال التالي:<syntaxhighlight lang="ruby">/hay/ =~ 'haystack' #=> 0 | |||
/y/.match('haystack') #=> #<MatchData "y"> | /y/.match('haystack') #=> #<MatchData "y"> | ||
</syntaxhighlight>إذا احتوت سلسلة نصية على | </syntaxhighlight>إذا احتوت سلسلة نصية على النمط، فسيقال أنها مُطابقة، أو تتطابقت السلسلة مع التعبير النمطي. كل سلسلة نصية حرفية (literal) تطابق نفسها. | ||
في المثال | في المثال التالي، السلسلة النصية <code>'haystack'</code> لا تحتوي على النمط <code>'needle'</code>، لذلك فهي غير متطابقة:<syntaxhighlight lang="ruby">/needle/.match('haystack') #=> nil | ||
</syntaxhighlight> | </syntaxhighlight>أما في المثال التالي، فالسلسلة النصية <code>'haystack'</code> تحتوي على السلسلة النصية الحرفية <code>'hay'</code>، لذلك فهي متطابقة:<syntaxhighlight lang="ruby">/hay/.match('haystack') #=> #<MatchData "hay"> | ||
</syntaxhighlight>بشكل أكثر تحديدًا، يتطلب التعبير النمطي <code>/st/</code> أن تحتوي السلسلة النصية على الحرف <code>s</code> | </syntaxhighlight>بشكل أكثر تحديدًا، يتطلب التعبير النمطي <code>/st/</code> أن تحتوي السلسلة النصية على الحرف <code>s</code> متبوعًا بالحرف <code>t</code>، لذلك فهي تتطابق مع <code>"haystack"</code> أيضًا. | ||
==المعامل <code>[[Ruby/Regexp/3D~|=~]]</code> و التابع <code>[[Ruby/Regexp/match|match]]</code>== | |||
== المعامل <code>[[Ruby/Regexp/3D~|=~]]</code> | |||
يمكن التحقق من مطابقة النمط باستخدام المعامل <code>[[Ruby/Regexp/3D~|=~]]</code> أو التابع <code>[[Ruby/Regexp/match|match]]</code>. | يمكن التحقق من مطابقة النمط باستخدام المعامل <code>[[Ruby/Regexp/3D~|=~]]</code> أو التابع <code>[[Ruby/Regexp/match|match]]</code>. | ||
===المعامل <code>[[Ruby/Regexp/3D~|=~]]</code>=== | |||
المعامل <code>[[Ruby/Regexp/3D~|=~]]</code> هو معامل المُطابقة الأساسي في روبي. عندما يكون أحد معاملاته عبارة عن تعبير نمطي، والآخر عبارة عن سلسلة نصية، فسيُستخدم التعبير النمطي حينها كنمط لمطابقة السلسلة النصية. (تعريف هذا المعامل في الصنفين <code>Regexp</code> و <code>[[Ruby/String|String]]</code> متماثل، لذا لا يهم ترتيب السلسلة النصية أو التعبير النمطي. قد يسلك هذا المعامل سلوكًا مختلفًا في الأصناف الأخرى.) | |||
في حالة العثور على تطابق، فسيعيد المعامل فهرس المطابقة الأولى في السلسلة النصية، وإلا فسيعيد <code>nil</code>.<syntaxhighlight lang="ruby">/hay/ =~ 'haystack' #=> 0 | |||
'haystack' =~ /hay/ #=> 0 | 'haystack' =~ /hay/ #=> 0 | ||
/a/ =~ 'haystack' #=> 1 | /a/ =~ 'haystack' #=> 1 | ||
/u/ =~ 'haystack' #=> nil</syntaxhighlight>عند استخدام المعامل <code>[[Ruby/Regexp/3D~|=~]]</code> مع كائن من النوع <code>[[Ruby/String|String]]</code> أو <code>Regexp</code>، سيتم تعيين المتغير العام <code>$~</code> بعد الحصول على مطابقة ناجحة. | /u/ =~ 'haystack' #=> nil</syntaxhighlight>عند استخدام المعامل <code>[[Ruby/Regexp/3D~|=~]]</code> مع كائن من النوع <code>[[Ruby/String|String]]</code> أو <code>Regexp</code>، سيتم تعيين المتغير العام <code>$~</code> بعد الحصول على مطابقة ناجحة. سيحتوي المتغير <code>$~</code> على كائن من النوع <code>[[Ruby/MatchData|MatchData]]</code>. | ||
التابع<code>[[Ruby/Regexp/last match|last_match]]</code> مكافئ للمتغير <code>$~</code>. | التابع <code>[[Ruby/Regexp/last match|last_match]]</code> مكافئ للمتغير <code>$~</code>. | ||
===التابع <code>[[Ruby/Regexp/match|match]]</code>=== | |||
=== التابع <code>[[Ruby/Regexp/match|match]]</code> === | |||
يعيد التابع <code>[[Ruby/Regexp/match|match]]</code> كائنًا من النوع <code>[[Ruby/MatchData|MatchData]]</code>:<syntaxhighlight lang="ruby">/st/.match('haystack') #=> #<MatchData "st"></syntaxhighlight> | يعيد التابع <code>[[Ruby/Regexp/match|match]]</code> كائنًا من النوع <code>[[Ruby/MatchData|MatchData]]</code>:<syntaxhighlight lang="ruby">/st/.match('haystack') #=> #<MatchData "st"></syntaxhighlight> | ||
==المحارف الخاصة ومحارف التهريب== | |||
المحارف التالية هي محارف خاصة (metacharacters): | |||
<code>(</code> ، <code>)</code> ، <code>[</code> ، <code>]</code> ، <code>{</code> ، <code>}</code> ، <code>.</code> ، <code>?</code> ، <code>+</code> ، <code>*</code>. | |||
لهذه المحارف معاني محددة عندما تظهر في تعبير نمطي. ولمطابقتها حرفيًا، يجب أن تكون مسبوقة بخط مائل عكسي <code>\</code>. لمطابقة الخظ المائل العكسي حرفيًا، فيجب أن يسبق هذا الخط بخط مائل عكسي آخر: <code>\\</code>. يعد الخط المائل العكسي الأول محرف تهريب للمحرف الذي يليه:<syntaxhighlight lang="ruby">/1 \+ 2 = 3\?/.match('Does 1 + 2 = 3?') #=> #<MatchData "1 + 2 = 3?"> | |||
/a\\\\b/.match('a\\\\b') #=> #<MatchData "a\\b"> | /a\\\\b/.match('a\\\\b') #=> #<MatchData "a\\b"> | ||
</syntaxhighlight>تتصرف الأنماط مثل السلاسل النصية المُقتبسة (double-quoted) بحيث يمكن أن تحتوي على نفس | </syntaxhighlight>تتصرف الأنماط مثل السلاسل النصية المُقتبسة (double-quoted) بحيث يمكن أن تحتوي على نفس الخط المائل العكسي المخصصة للتهريب (backslash escapes):<syntaxhighlight lang="ruby">/\s\u{6771 4eac 90fd}/.match("Go to 東京都") | ||
#=> #<MatchData " 東京都"> | #=> #<MatchData " 東京都"> | ||
</syntaxhighlight>يمكن تضمين تعابير روبي في الأنماط عبر الصياغة <code>#{...}</code>.<syntaxhighlight lang="ruby">place = "東京都" | </syntaxhighlight>يمكن تضمين تعابير روبي في الأنماط عبر الصياغة <code>#{...}</code>.<syntaxhighlight lang="ruby">place = "東京都" | ||
سطر 39: | سطر 40: | ||
#=> #<MatchData "東京都"> | #=> #<MatchData "東京都"> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==مجموعات الحروف (Character Classes)== | |||
يتم تحديد مجموعات الحروف (character class) بواسطة الأقواس المربعة (<code>[</code> ، <code>]</code>) وتوضع بينها المحارف التي قد تظهر عند هذه النقطة في المطابقة. التعبير النمطي <code>/[ab]/</code> يعني إما <code>a</code> أو <code>b</code>، على خلاف <code>/ab/</code> الذي يعني الحرف <code>a</code> متبوعًا بالحرف <code>b</code>.<syntaxhighlight lang="ruby">/W[aeiou]rd/.match("Word") #=> #<MatchData "Word"></syntaxhighlight>ضمن مجموعات الحروف، تمثل الشرطة (<code>-</code>) حرفًا خاصًّا يشير إلى مجال شامل (inclusive) مكون من أحرف. التعبير النمطي <code>[abcd]</code> يكافئ <code>[a-d]</code>. يمكن أن يُتبع المجال بمجال آخر، لذلك فالتعبير النمطي <code>[abcdwxyz]</code> يكافئ <code>[a-dw-z]</code>. ولا يهم الترتيب الذي تظهر به المجالات أو الأحرف الفردية داخل مجموعة الحروف.<syntaxhighlight lang="ruby">/[0-9a-f]/.match('9f') #=> #<MatchData "9"> | |||
/[9f]/.match('9f') #=> #<MatchData "9"></syntaxhighlight>إذا كان أول حرف من حروف المجموعة هو العلامة (<code>^</code>)، فسيُعكس سلوك المجموعة آنذاك؛ أي أنها ستطابق أي حرف باستثناء تلك المحددة في الأقواس المربعة.<syntaxhighlight lang="ruby">/[^a-eg-z]/.match('f') #=> #<MatchData "f"></syntaxhighlight>يمكن أن تحتوي مجموعة حروف على مجموعة حروف أخرى لشكل تشعبي. الشكل <code>[a-z[0-9]]</code> يصف نفس المجموعة <code>[a-z0-9]</code>. كما أنّ مجموعات الحروف تدعم المعامل <code>&&</code> الذي يجري عملية التقاطع على وسائطه. ويمكن دمج الاثنين كما يلي:<syntaxhighlight lang="ruby">/[a-w&&[^c-g]z]/ # ([a-w] AND ([^c-g] OR z))</syntaxhighlight>هذا يُكافئ:<syntaxhighlight lang="ruby">/[abh-w]/</syntaxhighlight>تتصرف المحارف الخاصة (metacharacters) التالية مثل مجموعات الحروف: | |||
*<code>/./</code> - أي حرف باستثناء محرف السطر الجديد. | |||
*<code>/./m</code> - أي حرف (المُعدِّل <code>m</code> يتيح الوضع متعدد الأسطر) | |||
*<code>/\w/</code> - حرف كلمة (<code>[a-zA-Z0-9_]</code>) | |||
*<code>/\W/</code> - ُحرف يخالف حروف الكلمة (<code>[^a-zA-Z0-9_]</code>). يرجى إلقاء نظرة على صفحة الخطأ <code>[https://bugs.ruby-lang.org/issues/4044 Bug#4044]</code> في حالة استخدام <code>/\W/</code> مع المُعدِّل <code>/i</code>. | |||
*<code>/\d/</code> - حرف رقمي ويكافئ (<code>[0-9]</code>) | |||
*<code>/\D/</code> - حرف غير رقمي ويكافئ (<code>[^0-9]</code>) | |||
*<code>/\h/</code> - حرف ستة عشري ويكافئ (<code>[0-9a-fA-F]</code>) | |||
* <code>/ | *<code>/\H/</code> - حرف غير ستة عشري ويكافئ (<code>[^0-9a-fA-F]</code>) | ||
* | *<code>/\s/</code> - حرف من حروف المسافات البيضاء، ويكافئ <code>/[ \t\r\n\f\v]/</code> | ||
* | *<code>/\S/</code> - حرف يخالف حروف المسافة البيضاء، ويكافئ <code>/[^ \t\r\n\f\v]/</code> | ||
تعبيرات أقواس POSIX (POSIX ''bracket expressions'') مشابهة لمجموعات الحروف في التعابير النمطية، إذ توفر بديلاً محمولًا (portable) لما سبق، مع ميزة إضافية تتمثل في أنها يمكن أن تحتوي على أحرف من خارج الترميز ASCII. على سبيل المثال، لا يطابق التعبير <code>/\d/</code> إلا الأرقام العشرية للترميز ASCII (0-9)؛ بينما يطابق التعبير <code>/<nowiki>[[:digit:]]</nowiki>/</code> أي حرف من مجموعة الحروف العددية Nd في اليونيكود (Unicode Nd). | |||
*<code>/<nowiki>[[:alnum:]]</nowiki>/</code>- حرف أبجدي أو رقم | |||
*<code>/<nowiki>[[:alpha:]]</nowiki>/</code> - حرف أبجدي | |||
*<code>/<nowiki>[[:blank:]]</nowiki>/</code> - فراغ أو علامة تبويب (tab) | |||
*<code>/<nowiki>[[:cntrl:]]</nowiki>/</code> - حرف تحكم (Control character) | |||
*<code>/<nowiki>[[:digit:]]</nowiki>/</code> - رقم | |||
*<code>/<nowiki>[[:graph:]]</nowiki>/</code> - حرف غير فارغ (يستثني المسافات وأحرف التحكم وما شابه) | |||
*<code>/<nowiki>[[:lower:]]</nowiki>/</code> - الأحرف الأبجدية الصغيرة | |||
*<code>/<nowiki>[[:print:]]</nowiki>/</code> - مثل <code>[:graph:]</code>، ولكنها تتضمن حرف المسافة | |||
*<code>/<nowiki>[[:punct:]]</nowiki>/</code> - علامة ترقيم (Punctuation character) | |||
*<code>/<nowiki>[[:space:]]</nowiki>/</code> - محرف مسافة بيضاء (<code>[:blank:]</code> أو سطر جديد أو حرف الرجوع [carriage return]، وما إلى ذلك) | |||
*<code>/<nowiki>[[:upper:]]</nowiki>/</code> - حرف أبجدي كبير | |||
*<code>/<nowiki>[[:xdigit:]]</nowiki>/</code> - رقم من الأرقام المسموح بها في الأعداد السداسي عشرية (أي الحروف <code>0-9a-fA-F</code>) | |||
* <code>/<nowiki>[[:digit:]]</nowiki>/</code> - رقم | |||
* <code>/<nowiki>[[:graph:]]</nowiki>/</code> - حرف غير فارغ (يستثني المسافات وأحرف التحكم وما شابه) | |||
* <code>/<nowiki>[[:lower:]]</nowiki>/</code> - الأحرف الأبجدية الصغيرة | |||
* <code>/<nowiki>[[:print:]]</nowiki>/</code> - مثل <code>[:graph:]</code>، ولكنها تتضمن حرف المسافة | |||
* <code>/<nowiki>[[:punct:]]</nowiki>/</code> - علامة ترقيم (Punctuation character) | |||
* <code>/<nowiki>[[:space:]]</nowiki>/</code> - محرف مسافة بيضاء (<code>[:blank:]</code> أو سطر جديد أو حرف الرجوع [carriage return]، وما إلى ذلك) | |||
* <code>/<nowiki>[[:upper:]]</nowiki>/</code> - حرف أبجدي كبير | |||
* <code>/<nowiki>[[:xdigit:]]</nowiki>/</code> - رقم من الأرقام المسموح بها في الأعداد السداسي عشرية (أي الحروف <code>0-9a-fA-F</code>) | |||
تدعم روبي أيضًا مجموعات الحروف التالية بجانب مجموعات POSIX: | تدعم روبي أيضًا مجموعات الحروف التالية بجانب مجموعات POSIX: | ||
* <code>/<nowiki>[[:word:]]</nowiki>/</code> - حرف من إحدى مجموعات حروف اليونيكود العامة التالية <code>Letter</code> و <code>Mark</code> و <code>Number</code> و <code>Connector_Punctuation</code> | *<code>/<nowiki>[[:word:]]</nowiki>/</code> - حرف من إحدى مجموعات حروف اليونيكود العامة التالية <code>Letter</code> و <code>Mark</code> و <code>Number</code> و <code>Connector_Punctuation</code> | ||
* <code>/<nowiki>[[:ascii:]]</nowiki>/</code> - حرف من مجموعة حروف ASCII | *<code>/<nowiki>[[:ascii:]]</nowiki>/</code> - حرف من مجموعة [[Arduino/asciichart|حروف ASCII]] | ||
<syntaxhighlight lang="ruby"># U+06F2 is "EXTENDED ARABIC-INDIC DIGIT TWO" | <syntaxhighlight lang="ruby"># U+06F2 is "EXTENDED ARABIC-INDIC DIGIT TWO" | ||
/[[:digit:]]/.match("\u06F2") #=> #<MatchData "\u{06F2}"> | /[[:digit:]]/.match("\u06F2") #=> #<MatchData "\u{06F2}"> | ||
/[[:upper:]][[:lower:]]/.match("Hello") #=> #<MatchData "He"> | /[[:upper:]][[:lower:]]/.match("Hello") #=> #<MatchData "He"> | ||
/[[:xdigit:]][[:xdigit:]]/.match("A6") #=> #<MatchData "A6"></syntaxhighlight> | /[[:xdigit:]][[:xdigit:]]/.match("A6") #=> #<MatchData "A6"></syntaxhighlight> | ||
==التكرار== | |||
== التكرار == | |||
تتطابق التركيبات الموصوفة حتى الآن مع حرف واحد، لكن ماذا لو أردنا مطابقة أكثر من حرف دفعة واحدة. يمكننا ذلك باستخدام حروف خاصة تُسمى المُكممات (quantifiers). والتي توضع بعد الحرف الذي نريد أن يتكرر لتحديد عدد مرات ظهوره، هذه المكممات هي: | تتطابق التركيبات الموصوفة حتى الآن مع حرف واحد، لكن ماذا لو أردنا مطابقة أكثر من حرف دفعة واحدة. يمكننا ذلك باستخدام حروف خاصة تُسمى المُكممات (quantifiers). والتي توضع بعد الحرف الذي نريد أن يتكرر لتحديد عدد مرات ظهوره، هذه المكممات هي: | ||
* <code>*</code> - صفر مرّة أو أكثر. | *<code>*</code> - صفر مرّة أو أكثر. | ||
* <code>+</code> - مرة واحدة أو أكثر | *<code>+</code> - مرة واحدة أو أكثر | ||
* <code>?</code> - صفر مرة أو مرة واحدة (اختياري) | *<code>?</code> - صفر مرة أو مرة واحدة (اختياري) | ||
* <code>{ | *<code>{n}</code> - بالضبط n مرة | ||
* <code>{ | *<code>{,n}</code> - على الأقل أكثر n مرة | ||
* <code>{, | *<code>{m,}</code> - على الأكثر m مرة | ||
* <code>{ | *<code>{n,m}</code> - بين n و m مرة | ||
إذا أردت مطابقة حرف كبير واحد (هو '<code>H</code>') على الأقل، ثم حرف واحد صغير على الأقل (مثل '<code>e</code>')، ثم حرفين <code>'l</code>'، ثم حرف '<code>o</code>':<syntaxhighlight lang="ruby">"Hello".match(/[[:upper:]]+[[:lower:]]+l{2}o/) #=> #<MatchData "Hello"></syntaxhighlight>أنماط التكرار طمّاعة (greedy) افتراضيًا: أي أنها تبحث عن مطابقة أكبر جزء ممكن يحقق المطابقة من السلسلة النصية. على خلاف ذلك، فإن المطابقة القانعة (lazy matching) تكتفي بالحد الأدنى من السلسلة النصية الذي يحقق المطابقة بشكل عام. | |||
يمكن جعل الحروف الخاصة الطماعة قانعة باتباعها بالحرف <code>?</code>. | يمكن جعل الحروف الخاصة الطماعة قانعة باتباعها بالحرف <code>?</code>. | ||
كلا النمطين أدناه يتطابقان مع السلسلة النصية. يستخدم الأول مُكمما طماعًا، بحيث يطابق "<code>.+</code>" السلسة النصية | كلا النمطين أدناه يتطابقان مع السلسلة النصية. يستخدم الأول مُكمما طماعًا، بحيث يطابق "<code>.+</code>" السلسة النصية '<nowiki><a><b>' ؛ أما الثاني فيستخدم مكمما قانعا، بحيث يطابق '</nowiki><code>.+?</code>'السلسلة النصية '<a>':<syntaxhighlight lang="ruby">/<.+>/.match("<a><b>") #=> #<MatchData "<a><b>"> | ||
/<.+?>/.match("<a><b>") #=> #<MatchData "<a>"></syntaxhighlight>المكممات المتبوعة بالعلامة <code>+</code> تُطابق تملكيًا (possessively): فبمجرد أن تُطابق نمطًا | /<.+?>/.match("<a><b>") #=> #<MatchData "<a>"></syntaxhighlight>المكممات المتبوعة بالعلامة <code>+</code> تُطابق تملكيًا (possessively): فبمجرد أن تُطابق نمطًا لن تتراجع. فهي تتصرف مثل المكممات الطماعة، ولكنها ترفض "التخلي" عن الأجزاء التي طابقتها حتى لو كان ذلك سيُفشل كامل المطابقة. | ||
==الالتقاط (Capturing)== | |||
== الالتقاط (Capturing) == | |||
يمكن استخدام الأقواس لأجل الالتقاط (capturing). ويمكن لاحقًا التأشير إلى النص المتضمن في مجموعة الأقواس رقم <code>n</code> بالعدد <code>n</code>. داخل النمط استخدم المؤشر <code>\n</code>، أما خارج النمط فاستخدم <code>MatchData[n]</code>. | يمكن استخدام الأقواس لأجل الالتقاط (capturing). ويمكن لاحقًا التأشير إلى النص المتضمن في مجموعة الأقواس رقم <code>n</code> بالعدد <code>n</code>. داخل النمط استخدم المؤشر <code>\n</code>، أما خارج النمط فاستخدم <code>MatchData[n]</code>. | ||
في المثال أدناه، | في المثال أدناه، تُلتقط "<code>at</code>" بالزوج الأول من الأقواس، ثم يتم التأشير إليها باستخدام <code>\1</code>:<syntaxhighlight lang="ruby">/[csh](..) [csh]\1 in/.match("The cat sat in the hat") | ||
<syntaxhighlight lang="ruby">/[csh](..) [csh]\1 in/.match("The cat sat in the hat") | #=> #<MatchData "cat sat in" 1:"at"></syntaxhighlight>يعيد التابع <code>[[Ruby/Regexp/match|match]]</code> كائنًا من النوع <code>[[Ruby/MatchData|MatchData]]</code>، والذي يجعل النص الذي تم التقاطه متاحًا عبر معامل الفهرسة <code>[]</code>:<syntaxhighlight lang="ruby">/[csh](..) [csh]\1 in/.match("The cat sat in the hat")[1] #=> 'at'</syntaxhighlight>يمكن التأشير إلى المجموعات الملتقطة باسمها الذي عُرّفت به في حال تعريفها وفق الصياغة <code>(<name>?)</code> أو <code>('name'?)</code>.<syntaxhighlight lang="ruby">/\$(?<dollars>\d+)\.(?<cents>\d+)/.match("$3.67") | ||
#=> #<MatchData "cat sat in" 1:"at"></syntaxhighlight> | |||
يعيد التابع <code>[[Ruby/Regexp/match|match]]</code> كائنًا من النوع <code>[[Ruby/MatchData|MatchData]]</code>، والذي يجعل النص الذي تم التقاطه متاحًا عبر معامل الفهرسة <code>[]</code>: | |||
<syntaxhighlight lang="ruby">/[csh](..) [csh]\1 in/.match("The cat sat in the hat")[1] #=> 'at'</syntaxhighlight> | |||
يمكن التأشير إلى المجموعات الملتقطة باسمها الذي عُرّفت به في حال تعريفها وفق الصياغة <code>( | |||
<syntaxhighlight lang="ruby">/\$(?<dollars>\d+)\.(?<cents>\d+)/.match("$3.67") | |||
#=> #<MatchData "$3.67" dollars:"3" cents:"67"> | #=> #<MatchData "$3.67" dollars:"3" cents:"67"> | ||
/\$(?<dollars>\d+)\.(?<cents>\d+)/.match("$3.67")[:dollars] #=> "3"</syntaxhighlight> | /\$(?<dollars>\d+)\.(?<cents>\d+)/.match("$3.67")[:dollars] #=> "3"</syntaxhighlight>يمكن التأشير إلى المجموعات المُسماة بواسطة <code>\k<name></code>، حيث <code>name</code> هو اسم المجموعة.<syntaxhighlight lang="ruby">/(?<vowel>[aeiou]).\k<vowel>.\k<vowel>/.match('ototomy') | ||
يمكن التأشير إلى المجموعات المُسماة بواسطة <code>\k< | #=> #<MatchData "ototo" vowel:"o"></syntaxhighlight>'''ملاحظة''': لا يمكن للتعبير النمطي استخدام المؤشرات المسماة (named backreferences) والمؤشرات الرقمية (numbered backreferences) في وقت واحد. عند استخدام مجموعات الالتقاط المسماة (named capture groups) مع تعبير نمطي حرفي على الجانب الأيسر من التعبير والمعامل <code>[[Ruby/Regexp/3D~|=~]]</code>، فسيتم تخزين النص الذي تم التقاطه في متغيرات محلية تحمل أسماء مشابهة.<syntaxhighlight lang="ruby">/\$(?<dollars>\d+)\.(?<cents>\d+)/ =~ "$3.67" #=> 0 | ||
<syntaxhighlight lang="ruby">/(?<vowel>[aeiou]).\k<vowel>.\k<vowel>/.match('ototomy') | |||
#=> #<MatchData "ototo" vowel:"o"></syntaxhighlight> | |||
'''ملاحظة''': لا يمكن للتعبير النمطي استخدام المؤشرات المسماة (named backreferences) والمؤشرات الرقمية (numbered backreferences) في وقت واحد. عند استخدام مجموعات الالتقاط المسماة (named capture groups) مع تعبير نمطي حرفي على الجانب الأيسر من التعبير والمعامل <code>[[Ruby/Regexp/3D~|=~]]</code>، فسيتم تخزين النص الذي تم التقاطه في متغيرات محلية تحمل أسماء مشابهة. | |||
<syntaxhighlight lang="ruby">/\$(?<dollars>\d+)\.(?<cents>\d+)/ =~ "$3.67" #=> 0 | |||
dollars #=> "3"</syntaxhighlight> | dollars #=> "3"</syntaxhighlight> | ||
==التجميع (Grouping)== | |||
تُجمّع (group) الأقواس التعابير التي تُطوّقها، مما يسمح بتحديدها كمجموعة واحدة. يتطابق النمط أدناه مع حرف متحرك (vowel) متبوع بحرفين من حروف كلمة (word characters):<syntaxhighlight lang="ruby">/[aeiou]\w{2}/.match("Caenorhabditis elegans") #=> #<MatchData "aen"></syntaxhighlight>بينما يتطابق النمط التالي مع حرف متحرك يتبعه حرف كلمة، مرتين، أي <code>[aeiou]\w[aeiou]\w</code>:<syntaxhighlight lang="ruby">/([aeiou]\w){2}/.match("Caenorhabditis elegans") | |||
#=> #<MatchData "enor" 1:"or"></syntaxhighlight>يتيح التعبير <code>(?:…)</code> إمكانية التجميع، لكن بدون التقاط. هذا يعني أنه يُجمّع التعابير التي يحتوي عليها في وحدة غير قابلة للتجزيئ (atom) دون إنشاء مؤشر إليها (backreference). هذا يفيد في تحسين الأداء، لكن على حساب إضرار طفيف بقابلية القراءة. | |||
في المثال أدناه، الزوج الأول من الأقواس يلتقط "<code>n</code>"، أما الثاني فيلتقط "<code>ti</code>". تتم الإشارة إلى المجموعة الثانية لاحقًا باستخدام المؤشر <code>\2</code>:<syntaxhighlight lang="ruby">/I(n)ves(ti)ga\2ons/.match("Investigations") | |||
#=> #<MatchData "Investigations" 1:"n" 2:"ti"></syntaxhighlight>لقط أصبح الزوج الأول من الأقواس غير قابل للالتقاط بسبب استخدام <code>?:</code>، لذلك سيتطابق مع "<code>n</code>"، ولكنه لن ينشئ مؤشرًا إليه. وبالتالي ، فالمؤشر <code>\1</code> يشير الآن إلى "<code>ti</code>".<syntaxhighlight lang="ruby">/I(?:n)ves(ti)ga\1ons/.match("Investigations") | |||
في المثال أدناه، الزوج الأول من الأقواس يلتقط "<code>n</code>"، أما الثاني فيلتقط "<code>ti</code>". تتم الإشارة إلى المجموعة الثانية لاحقًا باستخدام المؤشر <code>\2</code>: | |||
<syntaxhighlight lang="ruby">/I(n)ves(ti)ga\2ons/.match("Investigations") | |||
#=> #<MatchData "Investigations" 1:"n" 2:"ti"></syntaxhighlight> | |||
لقط أصبح الزوج الأول من الأقواس غير قابل للالتقاط بسبب استخدام <code>?:</code>، لذلك | |||
<syntaxhighlight lang="ruby">/I(?:n)ves(ti)ga\1ons/.match("Investigations") | |||
#=> #<MatchData "Investigations" 1:"ti"></syntaxhighlight> | #=> #<MatchData "Investigations" 1:"ti"></syntaxhighlight> | ||
==التجميع الذري (Atomic Grouping)== | |||
يمكن جعل التجميعات ذرية بواسطة التعبير <code>(?>pat)</code>. هذا سيؤدي إلى مطابقة التعبير الجزئي (subexpression) بشكل مستقل عن بقية التعبير، بحيث أنّ ما يطابقه سيصبح ثابتًا لبقية المطابقة، ما لم يتم التخلي عن التعبير الجزئي بأكمله وإعادة النظر فيه لاحقًا. بهذه الطريقة، يعامل النمط <code>pat</code> باعتباره وحدة غير قابلة للتجزيئ (ذرة). | |||
يتم استخدام التجميع الذري عادة لتحسين أداء الأنماط، وكذلك لمنع إنشاء مؤشرات (backtracking) بدون داعٍ. | |||
يتطابق <code>"</code> في النمط أدناه مع الحرف الأول من السلسلة النصية، ثم يُطابق <code>.*</code> علامة التنصيص <code>"</code>. يؤدي هذا إلى فشل المطابقة الإجمالية، وهكذا فالنص المطابق للتعبير <code>.*</code> يُؤشّر إليه (backtracked) بموضع واحد، مما يجعل الحرف النهائي للسلسلة النصية متاحًا لمطابقة <code>"</code>:<syntaxhighlight lang="ruby">/".*"/.match('"Quote"') #=> #<MatchData "\"Quote\""></syntaxhighlight>إذا تم تجميع <code>.*</code> ذريًا، فسيرفض إنشاء مرجع للعلامة <code>"</code>، على الرغم من أنّ هذا سيعني أن المطابقة الإجمالية ستفشل<syntaxhighlight lang="ruby">/"(?>.*)"/.match('"Quote"') #=> nil</syntaxhighlight> | |||
==استدعاء التعابير الجزئية (Subexpression Calls)== | |||
تطابق الصياغة <code>\g<name></code> التعبير الجزئي السابق المسمى <code>name</code>، والذي يمكن أن يكون اسم مجموعة أو رقم. هذا مُختلف عن التأشير في كونه يعيد معالجة المجموعة بدلًا من مجرد محاولة إعادة مطابقة نفس النص. | |||
يتطابق النمط التالي مع الحرف <code>(</code> ويُحيله إلى المجموعة <code>paren</code>، ويحاول استدعاء التعبير الجزئي للمجموعة <code>paren</code> مرة أخرى، لكنه يفشل، ثم يطابق الحرف <code>)</code>:<syntaxhighlight lang="ruby">/\A(?<paren>\(\g<paren>*\))*\z/ =~ '()' | |||
يتطابق النمط التالي مع الحرف <code>(</code>ويُحيله إلى المجموعة <code>paren</code>، ويحاول استدعاء التعبير الجزئي للمجموعة <code>paren</code> مرة أخرى، لكنه يفشل، ثم يطابق الحرف <code>)</code>: | |||
<syntaxhighlight lang="ruby">/\A(?<paren>\(\g<paren>*\))*\z/ =~ '()' | |||
/\A(?<paren>\(\g<paren>*\))*\z/ =~ '(())' #=> 0 | /\A(?<paren>\(\g<paren>*\))*\z/ =~ '(())' #=> 0 | ||
# ^1 | # ^1 | ||
سطر 153: | سطر 127: | ||
# ^9 | # ^9 | ||
# ^10</syntaxhighlight> | # ^10</syntaxhighlight> | ||
# يطابق بداية السلسلة النصية، أي قبل الحرف الأول. | #يطابق بداية السلسلة النصية، أي قبل الحرف الأول. | ||
# يدخل مجموعة التقاط مسماة (named capture group) تحمل الاسم<code>paren</code> | #يدخل مجموعة التقاط مسماة (named capture group) تحمل الاسم <code>paren</code> | ||
# يطابق المحرف <code>(</code>، الحرف الأول في السلسلة النصية | #يطابق المحرف <code>(</code>، الحرف الأول في السلسلة النصية | ||
# يستدعي المجموعة <code>paren</code> مرة أخرى، أي يعاود الرجوع (recurses) مرة أخرى إلى الخطوة الثانية | #يستدعي المجموعة <code>paren</code> مرة أخرى، أي يعاود الرجوع (recurses) مرة أخرى إلى الخطوة الثانية | ||
# يعيد الدخول إلى المجموعة <code>paren</code> | #يعيد الدخول إلى المجموعة <code>paren</code> | ||
# يطابق المحرف <code>(</code>، الحرف الثاني في السلسلة النصية | #يطابق المحرف <code>(</code>، الحرف الثاني في السلسلة النصية | ||
# يحاول استدعاء <code>paren</code> للمرة الثالثة، ولكن يفشله، لأن ذلك من شأنه أن يمنع مطابقة ناجحة شاملة | #يحاول استدعاء <code>paren</code> للمرة الثالثة، ولكن يفشله، لأن ذلك من شأنه أن يمنع مطابقة ناجحة شاملة | ||
# يطابق المحرف <code>)</code>، أي الحرف الثالث في السلسلة النصية. | #يطابق المحرف <code>)</code>، أي الحرف الثالث في السلسلة النصية. | ||
# يحدد نهاية الاستدعاء العودي (recursive) الثاني | #يحدد نهاية الاستدعاء العودي (recursive) الثاني | ||
# يطابق المحرف <code>)</code>، الحرف الرابع في السلسلة النصية | #يطابق المحرف <code>)</code>، الحرف الرابع في السلسلة النصية | ||
# يطابق نهاية السلسلة النصية | #يطابق نهاية السلسلة النصية | ||
==البدائل (Alternation)== | |||
== البدائل (Alternation) == | يجمع الحرف الخاص (<code>|</code>) بين تعبيرين في تعبير واحد، إذ يطابق أيًا من هذين التعبيرين. فكل تعبير هو بديل ممكن.<syntaxhighlight lang="ruby">/\w(and|or)\w/.match("Feliformia") #=> #<MatchData "form" 1:"or"> | ||
/\w(and|or)\w/.match("furandi") #=> #<MatchData "randi" 1:"and"> | /\w(and|or)\w/.match("furandi") #=> #<MatchData "randi" 1:"and"> | ||
/\w(and|or)\w/.match("dissemblance") #=> nil</syntaxhighlight> | /\w(and|or)\w/.match("dissemblance") #=> nil</syntaxhighlight> | ||
==خاصيات الحروف (Character Properties)== | |||
تُطابق الصياغة <code>\p{}</code> الحروف ذات الخاصية المعطاة، وهي مشابهة لمجموعات أقواس POSIX. | |||
*<code>/p{Alnum}\/</code> - حرف أبجدي أو رقمي | |||
*<code>/p{Alpha}\/</code> - حرف أبجدي | |||
*<code>/p{Blank}\/</code> - مسافة بيضاء أو علامة تبويب (tab) | |||
*<code>/p{Cntrl}\/</code> - محرف تحكم (Control character) | |||
*<code>/p{Digit}\/</code> - رقم | |||
*<code>/p{Graph}\/</code> - حرف غير فارغ (يستثني المسافات البيضاء وأحرف التحكم وما شابه) | |||
*<code>/p{Lower}\/</code> - حرف أبجدي صغير | |||
*<code>/p{Print}\/</code> - مثل <code>\p{Graph}</code> ، ولكنه يتضمن المسافة البيضاء | |||
*<code>/p{Punct}/</code> - علامة ترقيم | |||
*<code>/p{Space}\/</code> - حرف مسافة بيضاء (<code>[:blank:]</code> أو سطر جديد أو حرف العودة إلى بداية السطر [carriage return]، ...إلخ) | |||
*<code>/p{Upper}\/</code> - حرف أبجدي كبير | |||
*<code>/p{XDigit}\/</code> - رقم من الأرقام المسموح بها في الأعداد السداسي عشرية (مثل 0-9a-fA-F) | |||
*<code>/p{Word}\/</code> - عنصر من إحدى مجموعات اليونيكود العامة التالية Letter، Mark، Number، Connector_Punctuation | |||
*<code>/p{ASCII}\/</code> - حرف من حروف ASCII. | |||
*<code>/p{Any}\/</code> - أي حرف من حروف اليونيكود (بما في ذلك الأحرف غير المعينة [unassigned]). | |||
*<code>/p{Assigned}\/</code> - حرف معين (assigned character). | |||
يمكن أيضًا مطابقة حرف من مجموعة الترميز الموحد "الفئة العامة" (General Category) بالنمط <code>\p{Ab}</code> حيث <code>Ab</code> يمثل اختصار المجموعة كما هو موضح أدناه:<syntaxhighlight lang="ruby"> | |||
/\p{L}/ - 'Letter' - "حرف" | |||
/\p{Ll}/ - 'Letter: Lowercase' - "حرف: صغير" | |||
/\p{ | /\p{Lm}/ - 'Letter: Mark' - "حرف: علامة" | ||
/\p{ | /\p{Lo}/ - 'Letter: Other' - "حرف: آخر" | ||
/\p{ | /\p{Lt}/ - 'Letter: Titlecase' - "حرف: عنوان" | ||
/\p{ | /\p{Lu}/ - 'Letter: Uppercase - "حرف: كبير" | ||
/\p{ | /\p{Lo}/ - 'Letter: Other' - "حرف: آخر" | ||
/\p{ | /\p{M}/ - 'Mark' - "علامة" | ||
/\p{ | /\p{Mn}/ - 'Mark: Nonspacing' - "علامة: بدون مساحات بيضاء" | ||
/\p{ | /\p{Mc}/ - 'Mark: Spacing Combining' - "علامة: تضمين المساحات البيضاء" | ||
/\p{ | /\p{Me}/ - 'Mark: Enclosing' - "علامة: الإغلاق" | ||
/\p{ | /\p{N}/ - 'Number' - "عدد" | ||
/\p{ | /\p{Nd}/ - 'Number: Decimal Digit' - "عدد: رقم عشري" | ||
/\p{ | /\p{Nl}/ - 'Number: Letter' - "عدد: حرف" | ||
/\p{ | /\p{No}/ - 'Number: Other' - "عدد: آخر" | ||
/\p{ | /\p{P}/ - 'Punctuation' - "علامة تنقيط" | ||
/\p{ | /\p{Pc}/ - 'Punctuation: Connector' - "علامة تنقيط: واصلة" | ||
/\p{ | /\p{Pd}/ - 'Punctuation: Dash' - "علامة تنقيط: شرطة" | ||
/\p{ | /\p{Ps}/ - 'Punctuation: Open' - "علامة تنقيط: فتح" | ||
/\p{ | /\p{Pe}/ - 'Punctuation: Close' - "علامة تنقيط: غلق" | ||
/\p{ | /\p{Pi}/ - 'Punctuation: Initial Quote' - "علامة تنقيط: علامة تنصيص ابتدائية" | ||
/\p{ | /\p{Pf}/ - 'Punctuation: Final Quote' - "علامة تنقيط: علامة تنصيص نهائية" | ||
/\p{ | /\p{Po}/ - 'Punctuation: Other' - "علامة تنقيط: أخرى" | ||
/\p{ | /\p{S}/ - 'Symbol' - "رمز" | ||
/\p{ | /\p{Sm}/ - 'Symbol: Math' - "رمز: رياضيات" | ||
/\p{ | /\p{Sc}/ - 'Symbol: Currency' - "رمز: عملة" | ||
/\p{ | /\p{Sk}/ - 'Symbol: Modifier' - "رمز: معدل" | ||
/\p{ | /\p{So}/ - 'Symbol: Other' - "رمز: آخر" | ||
/\p{ | /\p{Z}/ - 'Separator' - "فاصل" | ||
/\p{ | /\p{Zs}/ - 'Separator: Space' - "فاصل: مساحة بيضاء" | ||
/\p{ | /\p{Zl}/ - 'Separator: Line' - "فاصل:سطر" | ||
/\p{ | /\p{Zp}/ - 'Separator: Paragraph' - "فاصل: فقرة" | ||
/\p{ | /\p{C}/ - 'Other' - "أخرى" | ||
/\p{ | /\p{Cc}/ - 'Other: Control' - "أخرى: ضبط" | ||
/\p{ | /\p{Cf}/ - 'Other: Format' - "أخرى: تنسيق" | ||
/\p{ | /\p{Cn}/ - 'Other: Not Assigned' - "أخرى: غير معين" | ||
/\p{ | /\p{Co}/ - 'Other: Private Use' - "أخرى: استخدام خاص" | ||
/\p{ | /\p{Cs}/ - 'Other: Surrogate' - "أخرى: بديل" | ||
</syntaxhighlight>في الأخير، تطابق <code>\p{}</code> محارف خطوط الكتابة في الترميز الموحد (Unicode). الخطوط التالية مدعومة:<syntaxhighlight lang="text"> | |||
</syntaxhighlight>في الأخير، تطابق <code>\p{}</code> محارف خطوط | |||
Arabic, Armenian, Balinese, Bengali, Bopomofo, Braille, Buginese, Buhid, Canadian_Aboriginal, Carian, Cham, Cherokee, Common, Coptic, Cuneiform, Cypriot, Cyrillic, Deseret, Devanagari, Ethiopic, Georgian, Glagolitic, Gothic, Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hiragana, Inherited, Kannada, Katakana, Kayah_Li, Kharoshthi, Khmer, Lao, Latin, Lepcha, Limbu, Linear_B, Lycian, Lydian, Malayalam, Mongolian, Myanmar, New_Tai_Lue, Nko, Ogham, Ol_Chiki, Old_Italic, Old_Persian, Oriya, Osmanya, Phags_Pa, Phoenician, Rejang, Runic, Saurashtra, Shavian, Sinhala, Sundanese, Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le, Tamil, Telugu, Thaana, Thai, Tibetan, Tifinagh, Ugaritic, Vai, and Yi | Arabic, Armenian, Balinese, Bengali, Bopomofo, Braille, Buginese, Buhid, Canadian_Aboriginal, Carian, Cham, Cherokee, Common, Coptic, Cuneiform, Cypriot, Cyrillic, Deseret, Devanagari, Ethiopic, Georgian, Glagolitic, Gothic, Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hiragana, Inherited, Kannada, Katakana, Kayah_Li, Kharoshthi, Khmer, Lao, Latin, Lepcha, Limbu, Linear_B, Lycian, Lydian, Malayalam, Mongolian, Myanmar, New_Tai_Lue, Nko, Ogham, Ol_Chiki, Old_Italic, Old_Persian, Oriya, Osmanya, Phags_Pa, Phoenician, Rejang, Runic, Saurashtra, Shavian, Sinhala, Sundanese, Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le, Tamil, Telugu, Thaana, Thai, Tibetan, Tifinagh, Ugaritic, Vai, and Yi | ||
</syntaxhighlight> | </syntaxhighlight>المحرف <code>U+06E9</code> في الترميز الموحد يُسمى "موضع سجدة" (ARABIC PLACE of SAJDAH)، وينتمي إلى الخط العربي:<syntaxhighlight lang="ruby">/\p{Arabic}/.match("\u06E9") #=> #<MatchData "\u06E9"></syntaxhighlight>يمكن عكس جميع خصائص الأحرف عن طريق إضافة البادئة (<code>^</code>) إلى أسمائها. الحرف "<code>A</code>" ليس مُتضمّنًا في مجموعة الترميز الموحد Ll [التي تعني (Letter; Lowercase)]، لذلك تنجح المطابقة التالية:<syntaxhighlight lang="ruby">/\p{^Ll}/.match("A") #=> #<MatchData "A"></syntaxhighlight> | ||
يمكن عكس جميع خصائص الأحرف عن طريق إضافة البادئة (<code>^</code>) إلى أسمائها. الحرف "<code>A</code>" ليس مُتضمّنًا في مجموعة | ==المراسي== | ||
<syntaxhighlight lang="ruby">/\p{^Ll}/.match("A") #=> #<MatchData "A"></syntaxhighlight> | المراسي (Anchors) هي حروف خاصة تُطابق مواضع معدومة الطول بين الأحرف، وتربط المطابقة بموضع معين. | ||
*<code>^</code> - تطابق بداية السطر | |||
*<code>$</code> - تطابق نهاية السطر | |||
*<code>\A</code> - تطابق بداية السلسلة النصية | |||
*<code>\Z</code> - تطابق نهاية السلسلة النصية. إذا انتهت السلسلة النصية بسطر جديد، فستُطابق الموضع الموجود قبل السطر الجديد مباشرة | |||
*<code>\z</code> - تطابق نهاية السلسلة النصية | |||
*<code>G\</code> - تطابق أول موضع مطابقة: في توابع مثل <code>[[Ruby/String/gsub|String.gsub]]</code> و <code>[[Ruby/String/scan|String.scan]]</code>، تتغير عند كل تكرار. أي تتطابق في البداية مع بداية الموضوع، وفي كل تكرار تطابق مكان انتهاء المطابقة الأخيرة | |||
<syntaxhighlight lang="ruby">" a b c".gsub(/ /, '_') #=> "____a_b_c" | <syntaxhighlight lang="ruby">" a b c".gsub(/ /, '_') #=> "____a_b_c" | ||
" a b c".gsub(/\G /, '_') #=> "____a b c" | " a b c".gsub(/\G /, '_') #=> "____a b c" | ||
</syntaxhighlight> | </syntaxhighlight>في التوابع التي تأخذ موضعًا (اختياريًا)، مثل <code>[[Ruby/Regexp/match|Regexp.match]]</code> و <code>[[Ruby/String/match|String.match]]</code>، ستُطابق مكان بدء البحث.<syntaxhighlight lang="ruby">"hello, world".match(/,/, 3) #=> #<MatchData ","> | ||
في التوابع التي تأخذ موضعًا(اختياريًا)، مثل <code>Regexp | "hello, world".match(/\G,/, 3) #=> nil</syntaxhighlight> | ||
<syntaxhighlight lang="ruby">"hello, world".match(/,/, 3) #=> #<MatchData ","> | *<code>\b</code> - تطابق مواضع حدود الكلمات (word boundaries) عندما تكون خارج الأقواس؛ وتطابق محرف التراجع (backspace وهو 0x08) عندما تكون داخل الأقواس | ||
"hello, world".match(/\G,/, 3) #=> nil | *<code>\B</code> - تُطابق المواضع المخالفة لحدود الكلمات | ||
*<code>(?=pat)</code> - التوكيد الأمامي الإيجابي (Positive lookahead assertion): تتأكد من أنّ الأحرف التالية تتطابق مع <code>pat</code>، ولكن لا تتضمن تلك الأحرف في النص المُطابق | |||
*<code>\b</code> - تطابق مواضع حدود الكلمات عندما تكون خارج الأقواس؛ وتطابق محرف التراجع backspace | *<code>(?!pat)</code> - التوكيد الأمامي السلبي (Negative lookahead assertion): تتأكد من أنّ الأحرف التالية لا تتطابق مع <code>pat</code>، ولكن لا تتضمن تلك الأحرف في النص المُطابق | ||
<syntaxhighlight lang="ruby">/real/.match("surrealist") #=> #<MatchData "real"> | *<code>(?<=pat)</code> -التوكيد الخلفي الإيجابي (Positive lookbehind assertion): تتأكد من تطابق الأحرف السابقة مع <code>pat</code>، ولكنها لا تتضمّن تلك الأحرف في النص المُطابق | ||
*<code>(?<!pat)</code> - التوكيد الخلفي الإيجابي (Negative lookbehind assertion): تتأكد من أنّ الأحرف السابقة لا تتطابق مع <code>pat</code>، ولكنها لا تتضمن تلك الأحرف في النص المُطابق | |||
إرساء النمط عند بداية السلسلة النصية يفرض بدء المطابقة هناك. في المثال الآتي، لا تظهر "real" في بداية السلسلة النصية، لذلك تفشل المطابقة: | إذا لم يتم وضع مرساة (anchor) للنمط، فيمكنه أن يبدأ من أي نقطة في السلسلة النصية:<syntaxhighlight lang="ruby">/real/.match("surrealist") #=> #<MatchData "real"></syntaxhighlight>إرساء (Anchoring) النمط عند بداية السلسلة النصية يفرض بدء المطابقة هناك. في المثال الآتي، لا تظهر "<code>real</code>" في بداية السلسلة النصية، لذلك تفشل المطابقة:<syntaxhighlight lang="ruby">/\Areal/.match("surrealist") #=> nil</syntaxhighlight>تفشل المطابقة أدناه لأنه على الرغم من أن "<code>Demand</code>" تحتوي "<code>and</code>" ، فإنّ النمط لا يظهر عند حدود ا (word boundary).<syntaxhighlight lang="ruby">/\band/.match("Demand")</syntaxhighlight>في حين أنّه في المثال التالي السلسلة النصية "<code>and</code>" تم إرساؤها عند المواضع المخالفة لحدود الكلمات (non-word boundary)، لذلك، فبدلًا من مطابقة "<code>and</code>" الأولى، ستتطابق مع الحرف الرابع من "<code>demand</code>":<syntaxhighlight lang="ruby">/\Band.+/.match("Supply and demand curve") #=> #<MatchData "and curve"></syntaxhighlight>يستخدم النمط التالي التوكيد الأمامي الإيجابي و التوكيد الخلفي الإيجابي لمطابقة النص الوارد في الوسوم (tags) دون تضمين الوسوم في المطابقة:<syntaxhighlight lang="ruby">/(?<=<b>)\w+(?=<\/b>)/.match("Fortune favours the <b>bold</b>") | ||
<syntaxhighlight lang="ruby">/\Areal/.match("surrealist") #=> nil | #=> #<MatchData "bold"></syntaxhighlight> | ||
==الخيارات== | |||
تفشل المطابقة أدناه لأنه على الرغم من أن "Demand" تحتوي "and" ، فإنّ النمط لا يظهر عند حدود | يمكن أن يُعقب محدد النهاية للتعبير النمطي بحرف واحد أو أكثر يمثل الخيارات التي تتحكم في كيفية مطابقة النمط. | ||
<syntaxhighlight lang="ruby">/\band/.match("Demand") | *<code>/pat/i</code> - يتجاهل حالة الأحرف | ||
*<code>/pat/m</code> - تجعل <code>.</code> تطابق محرف السطر الجديد | |||
في حين أنّه في المثال التالي السلسلة النصية "and" تم إرساؤها عند | *<code>/pat/x</code> - تتجاهل المسافات البيضاء والتعليقات الموجودة في النمط | ||
<syntaxhighlight lang="ruby">/\Band.+/.match("Supply and demand curve") #=> #<MatchData "and curve"> | *<code>/pat/o</code> - تنفّذ عملية التلقيم<code>#{}</code> مرة واحدة فقط | ||
يمكن أيضًا تطبيق الخيارات <code>i</code> و <code>m</code> و <code>x</code> على مستوى التعابير الجزئية (subexpression) عبر الصياغة <code>(?on-off)</code>، والتي تفعّل الخيارات <code>on</code>، وتعطّل الخيارات <code>off</code> في التعبير المحاط بالأقواس.<syntaxhighlight lang="ruby">/a(?i:b)c/.match('aBc') #=> #<MatchData "aBc"> | |||
يستخدم النمط التالي | |||
<syntaxhighlight lang="ruby">/(?<=<b>)\w+(?=<\/b>)/.match("Fortune favours the <b>bold</b>") | |||
#=> #<MatchData "bold"> | |||
الخيارات | |||
<syntaxhighlight lang="ruby">/a(?i:b)c/.match('aBc') #=> #<MatchData "aBc"> | |||
/a(?i:b)c/.match('abc') #=> #<MatchData "abc"> | /a(?i:b)c/.match('abc') #=> #<MatchData "abc"> | ||
</syntaxhighlight> | </syntaxhighlight>كما يمكن استخدام الخيارات مع التابع <code>[[Ruby/Regexp/new|new]]</code>:<syntaxhighlight lang="ruby">Regexp.new("abc", Regexp::IGNORECASE) #=> /abc/i | ||
كما يمكن استخدام الخيارات مع <code>Regexp | |||
<syntaxhighlight lang="ruby">Regexp.new("abc", Regexp::IGNORECASE) #=> /abc/i | |||
Regexp.new("abc", Regexp::MULTILINE) #=> /abc/m | Regexp.new("abc", Regexp::MULTILINE) #=> /abc/m | ||
Regexp.new("abc # Comment", Regexp::EXTENDED) #=> /abc # Comment/x | Regexp.new("abc # Comment", Regexp::EXTENDED) #=> /abc # Comment/x | ||
Regexp.new("abc", Regexp::IGNORECASE | Regexp::MULTILINE) #=> /abc/mi | Regexp.new("abc", Regexp::IGNORECASE | Regexp::MULTILINE) #=> /abc/mi</syntaxhighlight> | ||
==وضع التراص (Free-Spacing Mode) والتعليقات== | |||
وضع | كما ذُكر أعلاه، يتيح الخيار <code>x</code> وضع التراص (free-spacing mode). حيث يتم تجاهل محارف المسافاة البيضاء (Literal white space) داخل النمط، ويفتتح محرف الشباك (#، يدعى octothorpe) تعليقًا يستمر إلى نهاية السطر. يسمح هذا بتنظيم مكونات النمط بطريقة تجعله أكثر قابلة للقراءة. | ||
<syntaxhighlight lang="ruby">float_pat = /\A | |||
في المثال التالي يطابق النمط عددًا ذا منازل عشرية اختيارية:<syntaxhighlight lang="ruby">float_pat = /\A | |||
[[:digit:]]+ # 1 or more digits before the decimal point | [[:digit:]]+ # 1 or more digits before the decimal point | ||
(\. # Decimal point | (\. # Decimal point | ||
سطر 316: | سطر 283: | ||
)? # The decimal point and following digits are optional | )? # The decimal point and following digits are optional | ||
\Z/x | \Z/x | ||
float_pat.match('3.14') #=> #<MatchData "3.14" 1:".14"> | float_pat.match('3.14') #=> #<MatchData "3.14" 1:".14"></syntaxhighlight>هناك عدة استراتيجيات لمطابقة المسافات البيضاء: | ||
*استخدام أنماط مثل <code>\s</code> أو <code>\p{Space}</code>. | |||
هناك عدة استراتيجيات لمطابقة المسافات البيضاء: * | *استخدام مسافات بيضاء مهرَّبة (escaped whitespace) مثل " <code>\</code>"، أي مسافة مسبوقة بخط مائل عكسي. | ||
<syntaxhighlight lang="ruby">r = Regexp.new("a".force_encoding("iso-8859-1"),Regexp::FIXEDENCODING) | *استخدام مجموعة حروف مثل <code>[ ]</code>. | ||
يمكن تضمين التعليقات في نمط لا يعتمد الخيار <code>x</code> (non-x pattern) باستخدام الصياغة <code>(?#comment)</code>، حيث يكون التعليق عبارة عن نص اعتباطي يتم تجاهله من محرك التعبير النمطي. | |||
لا يمكن أن تتضمن التعليقات المُتضمّنة في تعبير نمطي حرفي محرف إنهاء غير مهرَّب (unescaped terminator characters). | |||
==الترميز== | |||
يفترض أن تستخدم التعابير النمطية ترميز المصدر. يمكن تعديل هذا السلوك بأحد المُعدِّلات التالية. | |||
*<code>/''pat''/u</code> استعمال الترميز UTF-8 | |||
*<code>/''pat''/e</code> استعمال الترميز EUC-JP | |||
*<code>/''pat''/s</code> استعمال الترميز Windows-31J | |||
*<code>/''pat''/n</code> استعمال الترميز ASCII-8BIT | |||
يمكن مطابقة تعبير نمطي مع سلسلة نصية عندما يتشاركان في الترميز، أو إن كان ترميز التعبير النمطي هو US-ASCII، وترميز السلسلة النصية متوافق مع ASCII. | |||
في حال محاولة المطابقة بين ترميزات غير متوافقة، فسيُطلق الاستثناء <code>[[Ruby/Encoding/CompatibilityError|Encoding::CompatibilityError]]</code>. | |||
تتحقق الدالة المنطقية <code>[[Ruby/Regexp/fixed encoding-3F|fixed_encoding?]]</code> مما إذا كان للتعبير النمطي ترميز ثابت، ومتوافق مع الترميز ASCII. | |||
يمكن تثبيت ترميز التعبير النمطي بشكل صريح عبر تمرير الثابتة <code>[[Ruby/Regexp/FIXEDENCODING|Regexp::FIXEDENCODING]]</code> كوسيط ثانٍ للتابع [[Ruby/Regexp/new|<code>new</code>]]:<syntaxhighlight lang="ruby">r = Regexp.new("a".force_encoding("iso-8859-1"),Regexp::FIXEDENCODING) | |||
r =~ "a\u3042" | r =~ "a\u3042" | ||
# raises Encoding::CompatibilityError: incompatible encoding regexp match | # raises Encoding::CompatibilityError: incompatible encoding regexp match | ||
# (ISO-8859-1 regexp with UTF-8 string) | # (ISO-8859-1 regexp with UTF-8 string)</syntaxhighlight> | ||
==متغيرات عامة مخصصة (Special global variables)== | |||
متغيرات عامة | من المهم معرفة بعض المتغيرات العامة: | ||
<syntaxhighlight lang="ruby">m = /s(\w{2}).*(c)/.match('haystack') #=> #<MatchData "stac" 1:"ta" 2:"c"> | *<code>$~</code>: تكافئ <code>[[Ruby/Regexp/last match|last_match]]</code> | ||
*<code>$&</code>: تحتوي كامل النص المتطابق | |||
* :<code>$`</code>تحتوي السلسلة النصية التي تسبق التطابق | |||
*<code>$'</code>: تحتوي السلسلة النصية التي تعقب التطابق | |||
*<code>$1</code> و <code>$2</code> ...إلخ: تحتوي النص المُتطابق مع مجموعة الالتقاط الأولى، والثانية، ...إلخ. | |||
*<code>$+</code> تحتوي آخر مجموعة مُلتقطة. | |||
إليك المثال التالي:<syntaxhighlight lang="ruby">m = /s(\w{2}).*(c)/.match('haystack') #=> #<MatchData "stac" 1:"ta" 2:"c"> | |||
$~ #=> #<MatchData "stac" 1:"ta" 2:"c"> | $~ #=> #<MatchData "stac" 1:"ta" 2:"c"> | ||
Regexp.last_match #=> #<MatchData "stac" 1:"ta" 2:"c"> | Regexp.last_match #=> #<MatchData "stac" 1:"ta" 2:"c"> | ||
سطر 342: | سطر 331: | ||
$+ #=> "c" | $+ #=> "c" | ||
# same as m[-1] | # same as m[-1] | ||
</syntaxhighlight> | </syntaxhighlight>هذه المتغيرات العامة هي متغيرات مخصصة للمهام الفرعية (thread-local)، ومخصصة للتوابع المحلية (method-local). | ||
==الأداء== | |||
<syntaxhighlight lang="ruby">s = 'a' * 25 + 'd' + 'a' * 4 + 'c' | يمكن أن تؤدي بعض التجميعات غير السليمة في الصياغة إلى أداء سيئ جدًا. انظر المثال التالي:<syntaxhighlight lang="ruby">s = 'a' * 25 + 'd' + 'a' * 4 + 'c' | ||
#=> "aaaaaaaaaaaaaaaaaaaaaaaaadaaaac" | #=> "aaaaaaaaaaaaaaaaaaaaaaaaadaaaac"</syntaxhighlight>تتم مطابقة الأنماط التالية على الفور كما هو متوقع:<syntaxhighlight lang="ruby">/(b|a)/ =~ s #=> 0 | ||
<syntaxhighlight lang="ruby">/(b|a)/ =~ s #=> 0 | |||
/(b|a+)/ =~ s #=> 0 | /(b|a+)/ =~ s #=> 0 | ||
/(b|a+)*/ =~ s #=> 0 | /(b|a+)*/ =~ s #=> 0</syntaxhighlight>أما النمط التالي فيستغرق وقتًا أطول بشكل ملحوظ:<syntaxhighlight lang="ruby">/(b|a+)*c/ =~ s #=> 26</syntaxhighlight>يحدث هذا لأن الذرة (جزء من النمط لا يمكن تقسيمه) في التعبير النمطي مٌكمّمة (quantified) بواسطة كل من حرف <code>+</code> فوري متبوعة بحرف <code>*</code> بدون تحديد من منهما سيكون المتحكم في حرف معين. عدم الوضوح ينتج عنه أداء خطي فائق (super-linear performance). (راجع كتاب Mastering Regular Expressions، ص 222، للكاتب Jeffery Friedl لأجل تحليل أعمق). يمكن إصلاح هذه المشكلة عن طريق استخدام التجميع الذري (atomic grouping)، والذي يمنع التأشير غير الضروري:<syntaxhighlight lang="ruby">(start = Time.now) && /(b|a+)*c/ =~ s && (Time.now - start) | ||
<syntaxhighlight lang="ruby">/(b|a+)*c/ =~ s #=> 26 | |||
<syntaxhighlight lang="ruby">(start = Time.now) && /(b|a+)*c/ =~ s && (Time.now - start) | |||
#=> 24.702736882 | #=> 24.702736882 | ||
(start = Time.now) && /(?>b|a+)*c/ =~ s && (Time.now - start) | (start = Time.now) && /(?>b|a+)*c/ =~ s && (Time.now - start) | ||
#=> 0.000166571 | #=> 0.000166571 | ||
</syntaxhighlight> | </syntaxhighlight>يوضح المثال التالي حالة مشابهة، والتي استغرق تنفيذها حوالي 60 ثانية عندي. | ||
حروف "a" التسعة وعشرون الاختيارية تطابق السلسلة النصية، لكن هذا يمنع الحروف التسعة | |||
<syntaxhighlight lang="ruby">Regexp.new('a | مطابقة سلسلة نصية مكونة 29 حرف "<code>a</code>" مقابل نمط مؤلف من 29 حرف "<code>a</code>" اختياري يليه 29 إلزامي على النحو التالي:<syntaxhighlight lang="ruby">Regexp.new('a?' * 29 + 'a' * 29) =~ 'a' * 29 | ||
</syntaxhighlight>حروف "<code>a</code>" التسعة وعشرون الاختيارية تطابق السلسلة النصية، لكن هذا يمنع الحروف التسعة وعشرين الإلزامية الموالية من المطابقة. تتراجع روبي مرارًا وتكرارًا حتى تستوفي أكبر عدد ممكن من التطابقات الاختيارية دون التفريط في المطابقات التسعة وعشرين الإجبارية. من الواضح لنا أنه لا يمكن لأي من المطابقات الاختيارية أن تنجح، ولكن هذه الحقيقة ليست واضحة للأسف لروبي. أفضل طريقة لتحسين الأداء هي تقليل مقدار التراجع المطلوب إلى أقصى حد. في هذه الحالة، بدلًا من المطابقة الفردية للحروف 29 الاختيارية، يمكن مطابقة مجال اختياريً دفعة واحدة عبر التعبير <code>{0،29}</code>:<syntaxhighlight lang="ruby">Regexp.new('a{0,29}' + 'a' * 29) =~ 'a' * 29 | |||
</syntaxhighlight> | |||
==الثوابت (Constants)== | |||
===<code rel="mw:WikiLink" title="Ruby/Regexp/EXTENDED" href="Ruby/Regexp/EXTENDED">EXTENDED</code>=== | |||
انظر صفحتي التابعين <code>[[Ruby/Regexp/options|options]]</code> و <code>[[Ruby/Regexp/new|new]]</code>. | |||
=== <code rel="mw:WikiLink" title="Ruby/Regexp/FIXEDENCODING" href="Ruby/Regexp/FIXEDENCODING">FIXEDENCODING</code> === | |||
انظر صفحتي التابعين <code>[[Ruby/Regexp/options|options]]</code> و <code>[[Ruby/Regexp/new|new]]</code>. | |||
=== <code rel="mw:WikiLink" title="Ruby/Regexp/IGNORECASE" href="Ruby/Regexp/IGNORECASE">IGNORECASE</code> === | |||
انظر صفحتي التابعين <code>[[Ruby/Regexp/options|options]]</code> و <code>[[Ruby/Regexp/new|new]]</code>. | |||
=== <code rel="mw:WikiLink" title="Ruby/Regexp/MULTILINE" href="Ruby/Regexp/MULTILINE">MULTILINE</code> === | |||
انظر صفحتي التابعين <code>[[Ruby/Regexp/options|options]]</code> و <code>[[Ruby/Regexp/new|new]]</code>. | |||
=== <code rel="mw:WikiLink" title="Ruby/Regexp/NOENCODING" href="Ruby/Regexp/NOENCODING">NOENCODING</code> === | |||
انظر صفحتي التابعين <code>[[Ruby/Regexp/options|options]]</code> و <code>[[Ruby/Regexp/new|new]]</code>. | |||
==توابع الصنف العامة (Public Class Methods)== | ==توابع الصنف العامة (Public Class Methods)== | ||
===[[Ruby/Regexp/compile | | ===[[Ruby/Regexp/compile|<code>compile</code>]]=== | ||
اسم آخر للتابع <code>Regexp | اسم آخر للتابع <code>[[Ruby/Regexp/new|new]]</code>. | ||
===[[Ruby/Regexp/escape | | ===[[Ruby/Regexp/escape|<code>escape</code>]]=== | ||
يهرِّب أي محرف يمكن أن يكون له معنى خاص في التعبير النمطي ثم يعيد سلسلة نصية جديدة مهرَّبة، أو يعيد الكائن الذي استُدعي معه (<code>self</code>) في حال عدم تهريب أي محرف. | |||
===[[Ruby/Regexp/ | ===[[Ruby/Regexp/last match|<code>last_match</code>]]=== | ||
يُعيد | يُعيد كائنًا من النوع <code>[[Ruby/MatchData|MatchData]]</code> الذي تم إنشاؤه من آخر تطابق ناجح للنمط. | ||
===[[Ruby/Regexp/new | | ===[[Ruby/Regexp/new|<code>new</code>]]=== | ||
ينشئ | ينشئ تعبيرًا نمطيًّا جديدًا. | ||
===[[Ruby/Regexp/quote | | ===[[Ruby/Regexp/quote|<code>quote</code>]]=== | ||
يهرِّب أي محرف قد يكون له معنى خاص في التعبير النمطي ثم يُعيد سلسلة نصية جديدة مهرَّبة، أو يعيد الكائن الذي استُدعي معه (<code>self</code>) إذا لم يتم تهريب أي محرف. | |||
===[[Ruby/Regexp/ | ===[[Ruby/Regexp/try convert|<code>try_convert</code>]]=== | ||
يُحاول | يُحاول تحويل الكائن المُمرَّر إليه إلى كائن من النوع <code>Regexp</code>. | ||
===[[Ruby/Regexp/union | | ===[[Ruby/Regexp/union|<code>union</code>]]=== | ||
يُعيد | يُعيد كائن من النوع <code>Regexp</code>، والذي يمثل اتحاد الأنماط المُمرَّرة إليه. | ||
===[[Ruby/Regexp/ | ==توابع النسخة العامة (Public Instance Methods)== | ||
معامل | ===[[Ruby/Regexp/equality operator|<code>==</code>]]=== | ||
===[[Ruby/Regexp/ | يتحقق من تساوي تعبيران نمطيان. | ||
===[[Ruby/Regexp/case equality|<code>===</code>]]=== | |||
===[[Ruby/Regexp/ | يعد معامل تساوي الحالة (Case Equality)، إذ يتحقق من تطابق تعبير نمطي مع سلسلة نصية. | ||
يبحث | ===[[Ruby/Regexp/3D~|<code>=~</code>]]=== | ||
===[[Ruby/Regexp/casefold-3F | | يبحث عن تطابق للتعبير النمطي. | ||
يعيد | ===[[Ruby/Regexp/~|<code>~</code>]]=== | ||
===[[Ruby/Regexp/encoding | | يبحث عن مطابقة التعبير النمطي الذي استُدعي معه في محتويات المتغير <code>$_</code>. وهو مُكافئ للتعبير <code>rxp =~ $_</code>. | ||
يُعيد | ===[[Ruby/Regexp/casefold-3F|<code>casefold?</code>]]=== | ||
===[[Ruby/Regexp/eql-3F | | يعيد قيمة راية الحساسية لحالة الأحرف (case-insensitive flag). | ||
===[[Ruby/Regexp/encoding|<code>encoding</code>]]=== | |||
===[[Ruby/Regexp/ | يُعيد كائنًا من النوع <code>[[Ruby/Encoding|Encoding]]</code>، والذي يمثل ترميز الكائن الذي استُدعي معه. | ||
===[[Ruby/Regexp/eql-3F|<code>eql?</code>]]=== | |||
===[[Ruby/Regexp/hash | | يتحقق إن كان التعبير النمطي المعطى مساويًا للتعبير النمطي الذي استُدعي معه | ||
===[[Ruby/Regexp/fixed encoding-3F|<code>fixed_encoding?</code>]]=== | |||
===[[Ruby/Regexp/inspect | | يتحقق إن كان التعبير النمطي الذي استُدعي معه قابلًا للتطبيق على سلسلة نصية ذات ترميز متوافق مع الترميز ASCII. | ||
يعيد | ===[[Ruby/Regexp/hash|<code>hash</code>]]=== | ||
===[[Ruby/Regexp/match | | يحسب الشيفرة hash استنادًا إلى القيمة النصية وخيارات التعبير النطامي الذي استدعي معه. | ||
يُعيد | ===[[Ruby/Regexp/inspect|<code>inspect</code>]]=== | ||
===[[Ruby/Regexp/match-3F | | يعيد نسخة نصية منسقة من التعبير النمطي الذي استُدعي معه. | ||
===[[Ruby/Regexp/match|<code>match</code>]]=== | |||
===[[Ruby/Regexp/ | يُعيد كائنًا من النوع <code>[[Ruby/MatchData|MatchData]]</code> يصف المطابقة بين تعبير نمطي وسلسلة نصية، أو يعيد القيمة <code>nil</code> إذا لم يكن هناك تطابق. | ||
يُعيد | ===[[Ruby/Regexp/match-3F|<code>match?</code>]]=== | ||
===[[Ruby/Regexp/names | | يتحقق ما إذا كان التعبير النمطي المعطى قد تطابق (matched) أم لا دون تحديث المتغير <code>$~</code> والمتغيرات الأخرى ذات الصلة. | ||
يعيد | ===[[Ruby/Regexp/named captures|<code>named_captures</code>]]=== | ||
===[[Ruby/Regexp/options | | يُعيد [[Ruby/Hash|جدول Hash]] يحتوي معلومات حول الالتقاطات المسماة (named captures) للتعبير النمطي الذي استُدعي معه. | ||
يُعيد مجموعة البتات (bits) المقابلة للخيارات المستخدمة عند إنشاء | ===[[Ruby/Regexp/names|<code>names</code>]]=== | ||
===[[Ruby/Regexp/source | | يعيد قائمة بأسماء الأجزاء المُلتقطة (captures) على هيئة مصفوفة من سلاسل نصية. | ||
يعيد | ===[[Ruby/Regexp/options|<code>options</code>]]=== | ||
===[[Ruby/Regexp/ | يُعيد مجموعة البتات (bits) المقابلة للخيارات المستخدمة عند إنشاء التعبير النمطي الذي استُدعي معه. | ||
يُعيد | ===[[Ruby/Regexp/source|<code>source</code>]]=== | ||
يعيد السلسلة النصية الأصلية للنمط. | |||
===[[Ruby/Regexp/to s|<code>to_s</code>]]=== | |||
*[http://ruby-doc.org/core-2.5.1/Regexp.html | يُعيد سلسلة نصية تحتوي على التعبير النمطي وخياراته، باستخدام الصياغة <code>(?opts:source)</code>. | ||
== <span> مصادر</span> == | |||
*[http://ruby-doc.org/core-2.5.1/Regexp.html صفحة الصنف Regexp في توثيق روبي الرسمي.] |
المراجعة الحالية بتاريخ 12:22، 7 ديسمبر 2018
تمثل كائنات الصنف Regexp
التعابير النمطية التي تُستخدم لمطابقة نمط (pattern) معيّن في سلسلة نصية. تُنشَأ التعابير النمطية باستخدام الصياغتين /.../
و %r{...}
، أو باستعمال الباني new
.
التعابير النمطية هي أنماط تصف محتويات السلسلة النصية. يمكن استخدامها للتحقق من أنّ سلسلة نصية تحتوي على نمط معين، أو لاستخراج الأجزاء المُطابقة منها.
عادةً ما يتم تحديد التعبير النمطي بخط مائل (/) كما يوضح المثال التالي:
/hay/ =~ 'haystack' #=> 0
/y/.match('haystack') #=> #<MatchData "y">
إذا احتوت سلسلة نصية على النمط، فسيقال أنها مُطابقة، أو تتطابقت السلسلة مع التعبير النمطي. كل سلسلة نصية حرفية (literal) تطابق نفسها.
في المثال التالي، السلسلة النصية 'haystack'
لا تحتوي على النمط 'needle'
، لذلك فهي غير متطابقة:
/needle/.match('haystack') #=> nil
أما في المثال التالي، فالسلسلة النصية 'haystack'
تحتوي على السلسلة النصية الحرفية 'hay'
، لذلك فهي متطابقة:
/hay/.match('haystack') #=> #<MatchData "hay">
بشكل أكثر تحديدًا، يتطلب التعبير النمطي /st/
أن تحتوي السلسلة النصية على الحرف s
متبوعًا بالحرف t
، لذلك فهي تتطابق مع "haystack"
أيضًا.
المعامل =~
و التابع match
يمكن التحقق من مطابقة النمط باستخدام المعامل =~
أو التابع match
.
المعامل =~
المعامل =~
هو معامل المُطابقة الأساسي في روبي. عندما يكون أحد معاملاته عبارة عن تعبير نمطي، والآخر عبارة عن سلسلة نصية، فسيُستخدم التعبير النمطي حينها كنمط لمطابقة السلسلة النصية. (تعريف هذا المعامل في الصنفين Regexp
و String
متماثل، لذا لا يهم ترتيب السلسلة النصية أو التعبير النمطي. قد يسلك هذا المعامل سلوكًا مختلفًا في الأصناف الأخرى.)
في حالة العثور على تطابق، فسيعيد المعامل فهرس المطابقة الأولى في السلسلة النصية، وإلا فسيعيد nil
.
/hay/ =~ 'haystack' #=> 0
'haystack' =~ /hay/ #=> 0
/a/ =~ 'haystack' #=> 1
/u/ =~ 'haystack' #=> nil
عند استخدام المعامل =~
مع كائن من النوع String
أو Regexp
، سيتم تعيين المتغير العام $~
بعد الحصول على مطابقة ناجحة. سيحتوي المتغير $~
على كائن من النوع MatchData
.
التابع last_match
مكافئ للمتغير $~
.
التابع match
يعيد التابع match
كائنًا من النوع MatchData
:
/st/.match('haystack') #=> #<MatchData "st">
المحارف الخاصة ومحارف التهريب
المحارف التالية هي محارف خاصة (metacharacters):
(
، )
، [
، ]
، {
، }
، .
، ?
، +
، *
.
لهذه المحارف معاني محددة عندما تظهر في تعبير نمطي. ولمطابقتها حرفيًا، يجب أن تكون مسبوقة بخط مائل عكسي \
. لمطابقة الخظ المائل العكسي حرفيًا، فيجب أن يسبق هذا الخط بخط مائل عكسي آخر: \\
. يعد الخط المائل العكسي الأول محرف تهريب للمحرف الذي يليه:
/1 \+ 2 = 3\?/.match('Does 1 + 2 = 3?') #=> #<MatchData "1 + 2 = 3?">
/a\\\\b/.match('a\\\\b') #=> #<MatchData "a\\b">
تتصرف الأنماط مثل السلاسل النصية المُقتبسة (double-quoted) بحيث يمكن أن تحتوي على نفس الخط المائل العكسي المخصصة للتهريب (backslash escapes):
/\s\u{6771 4eac 90fd}/.match("Go to 東京都")
#=> #<MatchData " 東京都">
يمكن تضمين تعابير روبي في الأنماط عبر الصياغة #{...}
.
place = "東京都"
/#{place}/.match("Go to 東京都")
#=> #<MatchData "東京都">
مجموعات الحروف (Character Classes)
يتم تحديد مجموعات الحروف (character class) بواسطة الأقواس المربعة ([
، ]
) وتوضع بينها المحارف التي قد تظهر عند هذه النقطة في المطابقة. التعبير النمطي /[ab]/
يعني إما a
أو b
، على خلاف /ab/
الذي يعني الحرف a
متبوعًا بالحرف b
.
/W[aeiou]rd/.match("Word") #=> #<MatchData "Word">
ضمن مجموعات الحروف، تمثل الشرطة (-
) حرفًا خاصًّا يشير إلى مجال شامل (inclusive) مكون من أحرف. التعبير النمطي [abcd]
يكافئ [a-d]
. يمكن أن يُتبع المجال بمجال آخر، لذلك فالتعبير النمطي [abcdwxyz]
يكافئ [a-dw-z]
. ولا يهم الترتيب الذي تظهر به المجالات أو الأحرف الفردية داخل مجموعة الحروف.
/[0-9a-f]/.match('9f') #=> #<MatchData "9">
/[9f]/.match('9f') #=> #<MatchData "9">
إذا كان أول حرف من حروف المجموعة هو العلامة (^
)، فسيُعكس سلوك المجموعة آنذاك؛ أي أنها ستطابق أي حرف باستثناء تلك المحددة في الأقواس المربعة.
/[^a-eg-z]/.match('f') #=> #<MatchData "f">
يمكن أن تحتوي مجموعة حروف على مجموعة حروف أخرى لشكل تشعبي. الشكل [a-z[0-9]]
يصف نفس المجموعة [a-z0-9]
. كما أنّ مجموعات الحروف تدعم المعامل &&
الذي يجري عملية التقاطع على وسائطه. ويمكن دمج الاثنين كما يلي:
/[a-w&&[^c-g]z]/ # ([a-w] AND ([^c-g] OR z))
هذا يُكافئ:
/[abh-w]/
تتصرف المحارف الخاصة (metacharacters) التالية مثل مجموعات الحروف:
/./
- أي حرف باستثناء محرف السطر الجديد.-
/./m
- أي حرف (المُعدِّلm
يتيح الوضع متعدد الأسطر) -
/\w/
- حرف كلمة ([a-zA-Z0-9_]
) -
/\W/
- ُحرف يخالف حروف الكلمة ([^a-zA-Z0-9_]
). يرجى إلقاء نظرة على صفحة الخطأBug#4044
في حالة استخدام/\W/
مع المُعدِّل /i
.
-
/\d/
- حرف رقمي ويكافئ ([0-9]
) -
/\D/
- حرف غير رقمي ويكافئ ([^0-9]
) -
/\h/
- حرف ستة عشري ويكافئ ([0-9a-fA-F]
) -
/\H/
- حرف غير ستة عشري ويكافئ ([^0-9a-fA-F]
) -
/\s/
- حرف من حروف المسافات البيضاء، ويكافئ/[ \t\r\n\f\v]/
-
/\S/
- حرف يخالف حروف المسافة البيضاء، ويكافئ/[^ \t\r\n\f\v]/
تعبيرات أقواس POSIX (POSIX bracket expressions) مشابهة لمجموعات الحروف في التعابير النمطية، إذ توفر بديلاً محمولًا (portable) لما سبق، مع ميزة إضافية تتمثل في أنها يمكن أن تحتوي على أحرف من خارج الترميز ASCII. على سبيل المثال، لا يطابق التعبير /\d/
إلا الأرقام العشرية للترميز ASCII (0-9)؛ بينما يطابق التعبير /[[:digit:]]/
أي حرف من مجموعة الحروف العددية Nd في اليونيكود (Unicode Nd).
/[[:alnum:]]/
- حرف أبجدي أو رقم/[[:alpha:]]/
- حرف أبجدي/[[:blank:]]/
- فراغ أو علامة تبويب (tab)/[[:cntrl:]]/
- حرف تحكم (Control character)
/[[:digit:]]/
- رقم/[[:graph:]]/
- حرف غير فارغ (يستثني المسافات وأحرف التحكم وما شابه)/[[:lower:]]/
- الأحرف الأبجدية الصغيرة/[[:print:]]/
- مثل[:graph:]
، ولكنها تتضمن حرف المسافة/[[:punct:]]/
- علامة ترقيم (Punctuation character)/[[:space:]]/
- محرف مسافة بيضاء ([:blank:]
أو سطر جديد أو حرف الرجوع [carriage return]، وما إلى ذلك)/[[:upper:]]/
- حرف أبجدي كبير/[[:xdigit:]]/
- رقم من الأرقام المسموح بها في الأعداد السداسي عشرية (أي الحروف 0-9a-fA-F
)
تدعم روبي أيضًا مجموعات الحروف التالية بجانب مجموعات POSIX:
/[[:word:]]/
- حرف من إحدى مجموعات حروف اليونيكود العامة التاليةLetter
وMark
وNumber
وConnector_Punctuation
/[[:ascii:]]/
- حرف من مجموعة حروف ASCII
# U+06F2 is "EXTENDED ARABIC-INDIC DIGIT TWO"
/[[:digit:]]/.match("\u06F2") #=> #<MatchData "\u{06F2}">
/[[:upper:]][[:lower:]]/.match("Hello") #=> #<MatchData "He">
/[[:xdigit:]][[:xdigit:]]/.match("A6") #=> #<MatchData "A6">
التكرار
تتطابق التركيبات الموصوفة حتى الآن مع حرف واحد، لكن ماذا لو أردنا مطابقة أكثر من حرف دفعة واحدة. يمكننا ذلك باستخدام حروف خاصة تُسمى المُكممات (quantifiers). والتي توضع بعد الحرف الذي نريد أن يتكرر لتحديد عدد مرات ظهوره، هذه المكممات هي:
*
- صفر مرّة أو أكثر.+
- مرة واحدة أو أكثر?
- صفر مرة أو مرة واحدة (اختياري){n}
- بالضبط n مرة{,n}
- على الأقل أكثر n مرة{m,}
- على الأكثر m مرة{n,m}
- بين n و m مرة
إذا أردت مطابقة حرف كبير واحد (هو 'H
') على الأقل، ثم حرف واحد صغير على الأقل (مثل 'e
')، ثم حرفين 'l
'، ثم حرف 'o
':
"Hello".match(/[[:upper:]]+[[:lower:]]+l{2}o/) #=> #<MatchData "Hello">
أنماط التكرار طمّاعة (greedy) افتراضيًا: أي أنها تبحث عن مطابقة أكبر جزء ممكن يحقق المطابقة من السلسلة النصية. على خلاف ذلك، فإن المطابقة القانعة (lazy matching) تكتفي بالحد الأدنى من السلسلة النصية الذي يحقق المطابقة بشكل عام.
يمكن جعل الحروف الخاصة الطماعة قانعة باتباعها بالحرف ?
.
كلا النمطين أدناه يتطابقان مع السلسلة النصية. يستخدم الأول مُكمما طماعًا، بحيث يطابق ".+
" السلسة النصية '<a><b>' ؛ أما الثاني فيستخدم مكمما قانعا، بحيث يطابق '.+?
'السلسلة النصية '<a>':
/<.+>/.match("<a><b>") #=> #<MatchData "<a><b>">
/<.+?>/.match("<a><b>") #=> #<MatchData "<a>">
المكممات المتبوعة بالعلامة +
تُطابق تملكيًا (possessively): فبمجرد أن تُطابق نمطًا لن تتراجع. فهي تتصرف مثل المكممات الطماعة، ولكنها ترفض "التخلي" عن الأجزاء التي طابقتها حتى لو كان ذلك سيُفشل كامل المطابقة.
الالتقاط (Capturing)
يمكن استخدام الأقواس لأجل الالتقاط (capturing). ويمكن لاحقًا التأشير إلى النص المتضمن في مجموعة الأقواس رقم n
بالعدد n
. داخل النمط استخدم المؤشر \n
، أما خارج النمط فاستخدم MatchData[n]
.
في المثال أدناه، تُلتقط "at
" بالزوج الأول من الأقواس، ثم يتم التأشير إليها باستخدام \1
:
/[csh](..) [csh]\1 in/.match("The cat sat in the hat")
#=> #<MatchData "cat sat in" 1:"at">
يعيد التابع match
كائنًا من النوع MatchData
، والذي يجعل النص الذي تم التقاطه متاحًا عبر معامل الفهرسة []
:
/[csh](..) [csh]\1 in/.match("The cat sat in the hat")[1] #=> 'at'
يمكن التأشير إلى المجموعات الملتقطة باسمها الذي عُرّفت به في حال تعريفها وفق الصياغة (<name>?)
أو ('name'?)
.
/\$(?<dollars>\d+)\.(?<cents>\d+)/.match("$3.67")
#=> #<MatchData "$3.67" dollars:"3" cents:"67">
/\$(?<dollars>\d+)\.(?<cents>\d+)/.match("$3.67")[:dollars] #=> "3"
يمكن التأشير إلى المجموعات المُسماة بواسطة \k<name>
، حيث name
هو اسم المجموعة.
/(?<vowel>[aeiou]).\k<vowel>.\k<vowel>/.match('ototomy')
#=> #<MatchData "ototo" vowel:"o">
ملاحظة: لا يمكن للتعبير النمطي استخدام المؤشرات المسماة (named backreferences) والمؤشرات الرقمية (numbered backreferences) في وقت واحد. عند استخدام مجموعات الالتقاط المسماة (named capture groups) مع تعبير نمطي حرفي على الجانب الأيسر من التعبير والمعامل =~
، فسيتم تخزين النص الذي تم التقاطه في متغيرات محلية تحمل أسماء مشابهة.
/\$(?<dollars>\d+)\.(?<cents>\d+)/ =~ "$3.67" #=> 0
dollars #=> "3"
التجميع (Grouping)
تُجمّع (group) الأقواس التعابير التي تُطوّقها، مما يسمح بتحديدها كمجموعة واحدة. يتطابق النمط أدناه مع حرف متحرك (vowel) متبوع بحرفين من حروف كلمة (word characters):
/[aeiou]\w{2}/.match("Caenorhabditis elegans") #=> #<MatchData "aen">
بينما يتطابق النمط التالي مع حرف متحرك يتبعه حرف كلمة، مرتين، أي [aeiou]\w[aeiou]\w
:
/([aeiou]\w){2}/.match("Caenorhabditis elegans")
#=> #<MatchData "enor" 1:"or">
يتيح التعبير (?:…)
إمكانية التجميع، لكن بدون التقاط. هذا يعني أنه يُجمّع التعابير التي يحتوي عليها في وحدة غير قابلة للتجزيئ (atom) دون إنشاء مؤشر إليها (backreference). هذا يفيد في تحسين الأداء، لكن على حساب إضرار طفيف بقابلية القراءة.
في المثال أدناه، الزوج الأول من الأقواس يلتقط "n
"، أما الثاني فيلتقط "ti
". تتم الإشارة إلى المجموعة الثانية لاحقًا باستخدام المؤشر \2
:
/I(n)ves(ti)ga\2ons/.match("Investigations")
#=> #<MatchData "Investigations" 1:"n" 2:"ti">
لقط أصبح الزوج الأول من الأقواس غير قابل للالتقاط بسبب استخدام ?:
، لذلك سيتطابق مع "n
"، ولكنه لن ينشئ مؤشرًا إليه. وبالتالي ، فالمؤشر \1
يشير الآن إلى "ti
".
/I(?:n)ves(ti)ga\1ons/.match("Investigations")
#=> #<MatchData "Investigations" 1:"ti">
التجميع الذري (Atomic Grouping)
يمكن جعل التجميعات ذرية بواسطة التعبير (?>pat)
. هذا سيؤدي إلى مطابقة التعبير الجزئي (subexpression) بشكل مستقل عن بقية التعبير، بحيث أنّ ما يطابقه سيصبح ثابتًا لبقية المطابقة، ما لم يتم التخلي عن التعبير الجزئي بأكمله وإعادة النظر فيه لاحقًا. بهذه الطريقة، يعامل النمط pat
باعتباره وحدة غير قابلة للتجزيئ (ذرة).
يتم استخدام التجميع الذري عادة لتحسين أداء الأنماط، وكذلك لمنع إنشاء مؤشرات (backtracking) بدون داعٍ.
يتطابق "
في النمط أدناه مع الحرف الأول من السلسلة النصية، ثم يُطابق .*
علامة التنصيص "
. يؤدي هذا إلى فشل المطابقة الإجمالية، وهكذا فالنص المطابق للتعبير .*
يُؤشّر إليه (backtracked) بموضع واحد، مما يجعل الحرف النهائي للسلسلة النصية متاحًا لمطابقة "
:
/".*"/.match('"Quote"') #=> #<MatchData "\"Quote\"">
إذا تم تجميع .*
ذريًا، فسيرفض إنشاء مرجع للعلامة "
، على الرغم من أنّ هذا سيعني أن المطابقة الإجمالية ستفشل
/"(?>.*)"/.match('"Quote"') #=> nil
استدعاء التعابير الجزئية (Subexpression Calls)
تطابق الصياغة \g<name>
التعبير الجزئي السابق المسمى name
، والذي يمكن أن يكون اسم مجموعة أو رقم. هذا مُختلف عن التأشير في كونه يعيد معالجة المجموعة بدلًا من مجرد محاولة إعادة مطابقة نفس النص.
يتطابق النمط التالي مع الحرف (
ويُحيله إلى المجموعة paren
، ويحاول استدعاء التعبير الجزئي للمجموعة paren
مرة أخرى، لكنه يفشل، ثم يطابق الحرف )
:
/\A(?<paren>\(\g<paren>*\))*\z/ =~ '()'
/\A(?<paren>\(\g<paren>*\))*\z/ =~ '(())' #=> 0
# ^1
# ^2
# ^3
# ^4
# ^5
# ^6
# ^7
# ^8
# ^9
# ^10
- يطابق بداية السلسلة النصية، أي قبل الحرف الأول.
- يدخل مجموعة التقاط مسماة (named capture group) تحمل الاسم
paren
- يطابق المحرف
(
، الحرف الأول في السلسلة النصية - يستدعي المجموعة
paren
مرة أخرى، أي يعاود الرجوع (recurses) مرة أخرى إلى الخطوة الثانية - يعيد الدخول إلى المجموعة
paren
- يطابق المحرف
(
، الحرف الثاني في السلسلة النصية - يحاول استدعاء
paren
للمرة الثالثة، ولكن يفشله، لأن ذلك من شأنه أن يمنع مطابقة ناجحة شاملة - يطابق المحرف
)
، أي الحرف الثالث في السلسلة النصية. - يحدد نهاية الاستدعاء العودي (recursive) الثاني
- يطابق المحرف
)
، الحرف الرابع في السلسلة النصية - يطابق نهاية السلسلة النصية
البدائل (Alternation)
يجمع الحرف الخاص (|
) بين تعبيرين في تعبير واحد، إذ يطابق أيًا من هذين التعبيرين. فكل تعبير هو بديل ممكن.
/\w(and|or)\w/.match("Feliformia") #=> #<MatchData "form" 1:"or">
/\w(and|or)\w/.match("furandi") #=> #<MatchData "randi" 1:"and">
/\w(and|or)\w/.match("dissemblance") #=> nil
خاصيات الحروف (Character Properties)
تُطابق الصياغة \p{}
الحروف ذات الخاصية المعطاة، وهي مشابهة لمجموعات أقواس POSIX.
/p{Alnum}\/
- حرف أبجدي أو رقمي/p{Alpha}\/
- حرف أبجدي/p{Blank}\/
- مسافة بيضاء أو علامة تبويب (tab)/p{Cntrl}\/
- محرف تحكم (Control character)/p{Digit}\/
- رقم/p{Graph}\/
- حرف غير فارغ (يستثني المسافات البيضاء وأحرف التحكم وما شابه)/p{Lower}\/
- حرف أبجدي صغير/p{Print}\/
- مثل \p{Graph}
، ولكنه يتضمن المسافة البيضاء/p{Punct}/
- علامة ترقيم/p{Space}\/
- حرف مسافة بيضاء ([:blank:]
أو سطر جديد أو حرف العودة إلى بداية السطر [carriage return]، ...إلخ)/p{Upper}\/
- حرف أبجدي كبير/p{XDigit}\/
- رقم من الأرقام المسموح بها في الأعداد السداسي عشرية (مثل 0-9a-fA-F)/p{Word}\/
- عنصر من إحدى مجموعات اليونيكود العامة التالية Letter، Mark، Number، Connector_Punctuation/p{ASCII}\/
- حرف من حروف ASCII./p{Any}\/
- أي حرف من حروف اليونيكود (بما في ذلك الأحرف غير المعينة [unassigned])./p{Assigned}\/
- حرف معين (assigned character).
يمكن أيضًا مطابقة حرف من مجموعة الترميز الموحد "الفئة العامة" (General Category) بالنمط \p{Ab}
حيث Ab
يمثل اختصار المجموعة كما هو موضح أدناه:
/\p{L}/ - 'Letter' - "حرف"
/\p{Ll}/ - 'Letter: Lowercase' - "حرف: صغير"
/\p{Lm}/ - 'Letter: Mark' - "حرف: علامة"
/\p{Lo}/ - 'Letter: Other' - "حرف: آخر"
/\p{Lt}/ - 'Letter: Titlecase' - "حرف: عنوان"
/\p{Lu}/ - 'Letter: Uppercase - "حرف: كبير"
/\p{Lo}/ - 'Letter: Other' - "حرف: آخر"
/\p{M}/ - 'Mark' - "علامة"
/\p{Mn}/ - 'Mark: Nonspacing' - "علامة: بدون مساحات بيضاء"
/\p{Mc}/ - 'Mark: Spacing Combining' - "علامة: تضمين المساحات البيضاء"
/\p{Me}/ - 'Mark: Enclosing' - "علامة: الإغلاق"
/\p{N}/ - 'Number' - "عدد"
/\p{Nd}/ - 'Number: Decimal Digit' - "عدد: رقم عشري"
/\p{Nl}/ - 'Number: Letter' - "عدد: حرف"
/\p{No}/ - 'Number: Other' - "عدد: آخر"
/\p{P}/ - 'Punctuation' - "علامة تنقيط"
/\p{Pc}/ - 'Punctuation: Connector' - "علامة تنقيط: واصلة"
/\p{Pd}/ - 'Punctuation: Dash' - "علامة تنقيط: شرطة"
/\p{Ps}/ - 'Punctuation: Open' - "علامة تنقيط: فتح"
/\p{Pe}/ - 'Punctuation: Close' - "علامة تنقيط: غلق"
/\p{Pi}/ - 'Punctuation: Initial Quote' - "علامة تنقيط: علامة تنصيص ابتدائية"
/\p{Pf}/ - 'Punctuation: Final Quote' - "علامة تنقيط: علامة تنصيص نهائية"
/\p{Po}/ - 'Punctuation: Other' - "علامة تنقيط: أخرى"
/\p{S}/ - 'Symbol' - "رمز"
/\p{Sm}/ - 'Symbol: Math' - "رمز: رياضيات"
/\p{Sc}/ - 'Symbol: Currency' - "رمز: عملة"
/\p{Sk}/ - 'Symbol: Modifier' - "رمز: معدل"
/\p{So}/ - 'Symbol: Other' - "رمز: آخر"
/\p{Z}/ - 'Separator' - "فاصل"
/\p{Zs}/ - 'Separator: Space' - "فاصل: مساحة بيضاء"
/\p{Zl}/ - 'Separator: Line' - "فاصل:سطر"
/\p{Zp}/ - 'Separator: Paragraph' - "فاصل: فقرة"
/\p{C}/ - 'Other' - "أخرى"
/\p{Cc}/ - 'Other: Control' - "أخرى: ضبط"
/\p{Cf}/ - 'Other: Format' - "أخرى: تنسيق"
/\p{Cn}/ - 'Other: Not Assigned' - "أخرى: غير معين"
/\p{Co}/ - 'Other: Private Use' - "أخرى: استخدام خاص"
/\p{Cs}/ - 'Other: Surrogate' - "أخرى: بديل"
في الأخير، تطابق \p{}
محارف خطوط الكتابة في الترميز الموحد (Unicode). الخطوط التالية مدعومة:
Arabic, Armenian, Balinese, Bengali, Bopomofo, Braille, Buginese, Buhid, Canadian_Aboriginal, Carian, Cham, Cherokee, Common, Coptic, Cuneiform, Cypriot, Cyrillic, Deseret, Devanagari, Ethiopic, Georgian, Glagolitic, Gothic, Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hiragana, Inherited, Kannada, Katakana, Kayah_Li, Kharoshthi, Khmer, Lao, Latin, Lepcha, Limbu, Linear_B, Lycian, Lydian, Malayalam, Mongolian, Myanmar, New_Tai_Lue, Nko, Ogham, Ol_Chiki, Old_Italic, Old_Persian, Oriya, Osmanya, Phags_Pa, Phoenician, Rejang, Runic, Saurashtra, Shavian, Sinhala, Sundanese, Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le, Tamil, Telugu, Thaana, Thai, Tibetan, Tifinagh, Ugaritic, Vai, and Yi
المحرف U+06E9
في الترميز الموحد يُسمى "موضع سجدة" (ARABIC PLACE of SAJDAH)، وينتمي إلى الخط العربي:
/\p{Arabic}/.match("\u06E9") #=> #<MatchData "\u06E9">
يمكن عكس جميع خصائص الأحرف عن طريق إضافة البادئة (^
) إلى أسمائها. الحرف "A
" ليس مُتضمّنًا في مجموعة الترميز الموحد Ll [التي تعني (Letter; Lowercase)]، لذلك تنجح المطابقة التالية:
/\p{^Ll}/.match("A") #=> #<MatchData "A">
المراسي
المراسي (Anchors) هي حروف خاصة تُطابق مواضع معدومة الطول بين الأحرف، وتربط المطابقة بموضع معين.
^
- تطابق بداية السطر$
- تطابق نهاية السطر-
\A
- تطابق بداية السلسلة النصية -
\Z
- تطابق نهاية السلسلة النصية. إذا انتهت السلسلة النصية بسطر جديد، فستُطابق الموضع الموجود قبل السطر الجديد مباشرة -
\z
- تطابق نهاية السلسلة النصية
G\
- تطابق أول موضع مطابقة: في توابع مثلString.gsub
وString.scan
، تتغير عند كل تكرار. أي تتطابق في البداية مع بداية الموضوع، وفي كل تكرار تطابق مكان انتهاء المطابقة الأخيرة
" a b c".gsub(/ /, '_') #=> "____a_b_c"
" a b c".gsub(/\G /, '_') #=> "____a b c"
في التوابع التي تأخذ موضعًا (اختياريًا)، مثل Regexp.match
و String.match
، ستُطابق مكان بدء البحث.
"hello, world".match(/,/, 3) #=> #<MatchData ",">
"hello, world".match(/\G,/, 3) #=> nil
-
\b
- تطابق مواضع حدود الكلمات (word boundaries) عندما تكون خارج الأقواس؛ وتطابق محرف التراجع (backspace وهو 0x08) عندما تكون داخل الأقواس -
\B
- تُطابق المواضع المخالفة لحدود الكلمات (?=pat)
- التوكيد الأمامي الإيجابي (Positive lookahead assertion): تتأكد من أنّ الأحرف التالية تتطابق معpat
، ولكن لا تتضمن تلك الأحرف في النص المُطابق(?!pat)
- التوكيد الأمامي السلبي (Negative lookahead assertion): تتأكد من أنّ الأحرف التالية لا تتطابق معpat
، ولكن لا تتضمن تلك الأحرف في النص المُطابق(?<=pat)
-التوكيد الخلفي الإيجابي (Positive lookbehind assertion): تتأكد من تطابق الأحرف السابقة معpat
، ولكنها لا تتضمّن تلك الأحرف في النص المُطابق(?<!pat)
- التوكيد الخلفي الإيجابي (Negative lookbehind assertion): تتأكد من أنّ الأحرف السابقة لا تتطابق معpat
، ولكنها لا تتضمن تلك الأحرف في النص المُطابق
إذا لم يتم وضع مرساة (anchor) للنمط، فيمكنه أن يبدأ من أي نقطة في السلسلة النصية:
/real/.match("surrealist") #=> #<MatchData "real">
إرساء (Anchoring) النمط عند بداية السلسلة النصية يفرض بدء المطابقة هناك. في المثال الآتي، لا تظهر "real
" في بداية السلسلة النصية، لذلك تفشل المطابقة:
/\Areal/.match("surrealist") #=> nil
تفشل المطابقة أدناه لأنه على الرغم من أن "Demand
" تحتوي "and
" ، فإنّ النمط لا يظهر عند حدود ا (word boundary).
/\band/.match("Demand")
في حين أنّه في المثال التالي السلسلة النصية "and
" تم إرساؤها عند المواضع المخالفة لحدود الكلمات (non-word boundary)، لذلك، فبدلًا من مطابقة "and
" الأولى، ستتطابق مع الحرف الرابع من "demand
":
/\Band.+/.match("Supply and demand curve") #=> #<MatchData "and curve">
يستخدم النمط التالي التوكيد الأمامي الإيجابي و التوكيد الخلفي الإيجابي لمطابقة النص الوارد في الوسوم (tags) دون تضمين الوسوم في المطابقة:
/(?<=<b>)\w+(?=<\/b>)/.match("Fortune favours the <b>bold</b>")
#=> #<MatchData "bold">
الخيارات
يمكن أن يُعقب محدد النهاية للتعبير النمطي بحرف واحد أو أكثر يمثل الخيارات التي تتحكم في كيفية مطابقة النمط.
-
/pat/i
- يتجاهل حالة الأحرف -
/pat/m
- تجعل.
تطابق محرف السطر الجديد -
/pat/x
- تتجاهل المسافات البيضاء والتعليقات الموجودة في النمط -
/pat/o
- تنفّذ عملية التلقيم#{}
مرة واحدة فقط
يمكن أيضًا تطبيق الخيارات i
و m
و x
على مستوى التعابير الجزئية (subexpression) عبر الصياغة (?on-off)
، والتي تفعّل الخيارات on
، وتعطّل الخيارات off
في التعبير المحاط بالأقواس.
/a(?i:b)c/.match('aBc') #=> #<MatchData "aBc">
/a(?i:b)c/.match('abc') #=> #<MatchData "abc">
كما يمكن استخدام الخيارات مع التابع new
:
Regexp.new("abc", Regexp::IGNORECASE) #=> /abc/i
Regexp.new("abc", Regexp::MULTILINE) #=> /abc/m
Regexp.new("abc # Comment", Regexp::EXTENDED) #=> /abc # Comment/x
Regexp.new("abc", Regexp::IGNORECASE | Regexp::MULTILINE) #=> /abc/mi
وضع التراص (Free-Spacing Mode) والتعليقات
كما ذُكر أعلاه، يتيح الخيار x
وضع التراص (free-spacing mode). حيث يتم تجاهل محارف المسافاة البيضاء (Literal white space) داخل النمط، ويفتتح محرف الشباك (#، يدعى octothorpe) تعليقًا يستمر إلى نهاية السطر. يسمح هذا بتنظيم مكونات النمط بطريقة تجعله أكثر قابلة للقراءة.
في المثال التالي يطابق النمط عددًا ذا منازل عشرية اختيارية:
float_pat = /\A
[[:digit:]]+ # 1 or more digits before the decimal point
(\. # Decimal point
[[:digit:]]+ # 1 or more digits after the decimal point
)? # The decimal point and following digits are optional
\Z/x
float_pat.match('3.14') #=> #<MatchData "3.14" 1:".14">
هناك عدة استراتيجيات لمطابقة المسافات البيضاء:
- استخدام أنماط مثل
\s
أو \p{Space}
. - استخدام مسافات بيضاء مهرَّبة (escaped whitespace) مثل "
\
"، أي مسافة مسبوقة بخط مائل عكسي. - استخدام مجموعة حروف مثل
[ ]
.
يمكن تضمين التعليقات في نمط لا يعتمد الخيار x
(non-x pattern) باستخدام الصياغة (?#comment)
، حيث يكون التعليق عبارة عن نص اعتباطي يتم تجاهله من محرك التعبير النمطي.
لا يمكن أن تتضمن التعليقات المُتضمّنة في تعبير نمطي حرفي محرف إنهاء غير مهرَّب (unescaped terminator characters).
الترميز
يفترض أن تستخدم التعابير النمطية ترميز المصدر. يمكن تعديل هذا السلوك بأحد المُعدِّلات التالية.
-
/pat/u
استعمال الترميز UTF-8 -
/pat/e
استعمال الترميز EUC-JP /pat/s
استعمال الترميز Windows-31J-
/pat/n
استعمال الترميز ASCII-8BIT
يمكن مطابقة تعبير نمطي مع سلسلة نصية عندما يتشاركان في الترميز، أو إن كان ترميز التعبير النمطي هو US-ASCII، وترميز السلسلة النصية متوافق مع ASCII.
في حال محاولة المطابقة بين ترميزات غير متوافقة، فسيُطلق الاستثناء Encoding::CompatibilityError
.
تتحقق الدالة المنطقية fixed_encoding?
مما إذا كان للتعبير النمطي ترميز ثابت، ومتوافق مع الترميز ASCII.
يمكن تثبيت ترميز التعبير النمطي بشكل صريح عبر تمرير الثابتة Regexp::FIXEDENCODING
كوسيط ثانٍ للتابع new
:
r = Regexp.new("a".force_encoding("iso-8859-1"),Regexp::FIXEDENCODING)
r =~ "a\u3042"
# raises Encoding::CompatibilityError: incompatible encoding regexp match
# (ISO-8859-1 regexp with UTF-8 string)
متغيرات عامة مخصصة (Special global variables)
من المهم معرفة بعض المتغيرات العامة:
-
$~
: تكافئlast_match
-
$&
: تحتوي كامل النص المتطابق - :
$`
تحتوي السلسلة النصية التي تسبق التطابق -
$'
: تحتوي السلسلة النصية التي تعقب التطابق $1
و $2
...إلخ: تحتوي النص المُتطابق مع مجموعة الالتقاط الأولى، والثانية، ...إلخ.-
$+
تحتوي آخر مجموعة مُلتقطة.
إليك المثال التالي:
m = /s(\w{2}).*(c)/.match('haystack') #=> #<MatchData "stac" 1:"ta" 2:"c">
$~ #=> #<MatchData "stac" 1:"ta" 2:"c">
Regexp.last_match #=> #<MatchData "stac" 1:"ta" 2:"c">
$& #=> "stac"
# same as m[0]
$` #=> "hay"
# same as m.pre_match
$' #=> "k"
# same as m.post_match
$1 #=> "ta"
# same as m[1]
$2 #=> "c"
# same as m[2]
$3 #=> nil
# no third group in pattern
$+ #=> "c"
# same as m[-1]
هذه المتغيرات العامة هي متغيرات مخصصة للمهام الفرعية (thread-local)، ومخصصة للتوابع المحلية (method-local).
الأداء
يمكن أن تؤدي بعض التجميعات غير السليمة في الصياغة إلى أداء سيئ جدًا. انظر المثال التالي:
s = 'a' * 25 + 'd' + 'a' * 4 + 'c'
#=> "aaaaaaaaaaaaaaaaaaaaaaaaadaaaac"
تتم مطابقة الأنماط التالية على الفور كما هو متوقع:
/(b|a)/ =~ s #=> 0
/(b|a+)/ =~ s #=> 0
/(b|a+)*/ =~ s #=> 0
أما النمط التالي فيستغرق وقتًا أطول بشكل ملحوظ:
/(b|a+)*c/ =~ s #=> 26
يحدث هذا لأن الذرة (جزء من النمط لا يمكن تقسيمه) في التعبير النمطي مٌكمّمة (quantified) بواسطة كل من حرف +
فوري متبوعة بحرف *
بدون تحديد من منهما سيكون المتحكم في حرف معين. عدم الوضوح ينتج عنه أداء خطي فائق (super-linear performance). (راجع كتاب Mastering Regular Expressions، ص 222، للكاتب Jeffery Friedl لأجل تحليل أعمق). يمكن إصلاح هذه المشكلة عن طريق استخدام التجميع الذري (atomic grouping)، والذي يمنع التأشير غير الضروري:
(start = Time.now) && /(b|a+)*c/ =~ s && (Time.now - start)
#=> 24.702736882
(start = Time.now) && /(?>b|a+)*c/ =~ s && (Time.now - start)
#=> 0.000166571
يوضح المثال التالي حالة مشابهة، والتي استغرق تنفيذها حوالي 60 ثانية عندي.
مطابقة سلسلة نصية مكونة 29 حرف "a
" مقابل نمط مؤلف من 29 حرف "a
" اختياري يليه 29 إلزامي على النحو التالي:
Regexp.new('a?' * 29 + 'a' * 29) =~ 'a' * 29
حروف "a
" التسعة وعشرون الاختيارية تطابق السلسلة النصية، لكن هذا يمنع الحروف التسعة وعشرين الإلزامية الموالية من المطابقة. تتراجع روبي مرارًا وتكرارًا حتى تستوفي أكبر عدد ممكن من التطابقات الاختيارية دون التفريط في المطابقات التسعة وعشرين الإجبارية. من الواضح لنا أنه لا يمكن لأي من المطابقات الاختيارية أن تنجح، ولكن هذه الحقيقة ليست واضحة للأسف لروبي. أفضل طريقة لتحسين الأداء هي تقليل مقدار التراجع المطلوب إلى أقصى حد. في هذه الحالة، بدلًا من المطابقة الفردية للحروف 29 الاختيارية، يمكن مطابقة مجال اختياريً دفعة واحدة عبر التعبير {0،29}
:
Regexp.new('a{0,29}' + 'a' * 29) =~ 'a' * 29
الثوابت (Constants)
EXTENDED
انظر صفحتي التابعين options
و new
.
FIXEDENCODING
انظر صفحتي التابعين options
و new
.
IGNORECASE
انظر صفحتي التابعين options
و new
.
MULTILINE
انظر صفحتي التابعين options
و new
.
NOENCODING
انظر صفحتي التابعين options
و new
.
توابع الصنف العامة (Public Class Methods)
compile
اسم آخر للتابع new
.
escape
يهرِّب أي محرف يمكن أن يكون له معنى خاص في التعبير النمطي ثم يعيد سلسلة نصية جديدة مهرَّبة، أو يعيد الكائن الذي استُدعي معه (self
) في حال عدم تهريب أي محرف.
last_match
يُعيد كائنًا من النوع MatchData
الذي تم إنشاؤه من آخر تطابق ناجح للنمط.
new
ينشئ تعبيرًا نمطيًّا جديدًا.
quote
يهرِّب أي محرف قد يكون له معنى خاص في التعبير النمطي ثم يُعيد سلسلة نصية جديدة مهرَّبة، أو يعيد الكائن الذي استُدعي معه (self
) إذا لم يتم تهريب أي محرف.
try_convert
يُحاول تحويل الكائن المُمرَّر إليه إلى كائن من النوع Regexp
.
union
يُعيد كائن من النوع Regexp
، والذي يمثل اتحاد الأنماط المُمرَّرة إليه.
توابع النسخة العامة (Public Instance Methods)
==
يتحقق من تساوي تعبيران نمطيان.
===
يعد معامل تساوي الحالة (Case Equality)، إذ يتحقق من تطابق تعبير نمطي مع سلسلة نصية.
=~
يبحث عن تطابق للتعبير النمطي.
~
يبحث عن مطابقة التعبير النمطي الذي استُدعي معه في محتويات المتغير $_
. وهو مُكافئ للتعبير rxp =~ $_
.
casefold?
يعيد قيمة راية الحساسية لحالة الأحرف (case-insensitive flag).
encoding
يُعيد كائنًا من النوع Encoding
، والذي يمثل ترميز الكائن الذي استُدعي معه.
eql?
يتحقق إن كان التعبير النمطي المعطى مساويًا للتعبير النمطي الذي استُدعي معه
fixed_encoding?
يتحقق إن كان التعبير النمطي الذي استُدعي معه قابلًا للتطبيق على سلسلة نصية ذات ترميز متوافق مع الترميز ASCII.
hash
يحسب الشيفرة hash استنادًا إلى القيمة النصية وخيارات التعبير النطامي الذي استدعي معه.
inspect
يعيد نسخة نصية منسقة من التعبير النمطي الذي استُدعي معه.
match
يُعيد كائنًا من النوع MatchData
يصف المطابقة بين تعبير نمطي وسلسلة نصية، أو يعيد القيمة nil
إذا لم يكن هناك تطابق.
match?
يتحقق ما إذا كان التعبير النمطي المعطى قد تطابق (matched) أم لا دون تحديث المتغير $~
والمتغيرات الأخرى ذات الصلة.
named_captures
يُعيد جدول Hash يحتوي معلومات حول الالتقاطات المسماة (named captures) للتعبير النمطي الذي استُدعي معه.
names
يعيد قائمة بأسماء الأجزاء المُلتقطة (captures) على هيئة مصفوفة من سلاسل نصية.
options
يُعيد مجموعة البتات (bits) المقابلة للخيارات المستخدمة عند إنشاء التعبير النمطي الذي استُدعي معه.
source
يعيد السلسلة النصية الأصلية للنمط.
to_s
يُعيد سلسلة نصية تحتوي على التعبير النمطي وخياراته، باستخدام الصياغة (?opts:source)
.