الكائن RegExp في JavaScript

من موسوعة حسوب
< JavaScript
مراجعة 08:16، 4 فبراير 2018 بواسطة عبد اللطيف ايمش (نقاش | مساهمات) (إزالة أزرار التعديل من عناوين الأقسام)
(فرق) → مراجعة أقدم | المراجعة الحالية (فرق) | مراجعة أحدث ← (فرق)
اذهب إلى التنقل اذهب إلى البحث

الكائن RegExp هو دالةٌ بانيةٌ تُنشِئ تعابير نمطيةً (regular expressions) لمُطابَقة النص مع نمط.

البنية العامة

يمكن أن تأخذ التعابير النمطية الشكل الآتي (الشكل المختصر، ثم الدالة البانية، ثم الدالة RegExp):

/pattern/flags
new RegExp(pattern[, flags])
RegExp(pattern[, flags])

pattern

التعبير النمطي.

flags

إذا حُدِّدَت قيمة هذا الوسيط، فستحتوي على تجميعة من الرايات الآتية.

g

المطابقة في كامل السلسلة النصية، أي العثور على جميع المطابقات بدل التوقف عند أوّل مطابقة.

i

تجاهل حالة الأحرف.

m

تعدد الأسطر، أي معاملة محرف البداية والنهاية (أي ^ و $) على أكثر من سطر (أي ستُطابِق بداية ونهاية كل سطر [التي يفصل بينها باستخدام محرف ‎\n أو ‎\r] وليس بداية ونهاية السلسلة النصية كلها).

u

سلسلة يونيكود، أي معاملة النمط على أنه سلسلة من رموز يونيكود (Unicode code points).

y

المطابقة ستبدأ من الفهرس المُشار إليه بالخاصية lastIndex لكائن التعابير النمطية في السلسلة الهدف، ولن تتم محاولة مطابقة ما قبل هذا الفهرس.

الوصف

هنالك طريقتان لإنشاء كائن RegExp: الشكل المختصر والدالة البانية. لاحظ أنَّ الشكل المختصر لا يُحاط بعلامتَي اقتباس، لكن الوسائط المُمرَّرة إلى الدالة البانية يمكن أن تُحاط بعلامتَي اقتباس؛ أي أنَّ الأشكال الآتية متكافئة:

/ab+c/i;
new RegExp('ab+c', 'i');
new RegExp(/ab+c/, 'i');

الشكل المختصر يؤدي إلى «بناء» التعبير النمطي عند تقدير قيمة التعبير الذي يحتويه. استخدم الشكل المختصر عندما تتأكد أنَّ التعبير النمطي سيبقى كما هو؛ أي لو استخدمتَ الشكل المختصر لإنشاء تعبير نمطي مستخدم في حلقة تكرار، فلن يُعاد بناء التعبير في كل تكرار.

أما الدالة البانية (مثلًا: new RegExp('ab+c')‎) توفِّر بناءً في وقت التنفيذ للتعبير النمطي. استخدم الدالة البانية عندما تعلم أنَّ التعبير النمطي سيتغيّر، أو عندما لا تعرف النمط وتريد الحصول عليه من مصدرٍ خارجي مثل مدخلات المستخدم.

بدءًا من إصدار ECMAScript 2015 (أي ES6) فإنَّ التعبير new RegExp(/ab+c/, 'i')‎ لن يُسبِّب برمي الخطأ TypeError (مع "can't supply flags when constructing one RegExp from another") وذلك عندما يكون أوّل وسيط هو تعبيرٌ نمطيٌ (من النوع RegExp) والوسيط flags موجودٌ.

عند استخدام الدالة البانية، لاحظ أنَّ قواعد تهريب المحارف التقليدية (أي إسباق المحارف الخاصة بشرطة مائلة خلفية \) ستكون ضروريةً. مثلًا:

var re = /\w+/;
var re = new RegExp('\\w+');

معاني المحارف الخاصة في التعابير النمطية

فئات المحارف

المحرف المعنى
. النقطة تُطابِق أي محرف ما عدا محارف نهاية السطر: ‎\n و ‎\r و ‎\u2028 و ‎\u2029.

أما داخل مجموعة محارف (character set) فستفقد النقطة معناها الخاص وستُطابِق محرف النقطة العادي. لاحظ أنَّ الراية m لا تُغيّر من سلوك النقطة.

على سبيل المثال، التعبير ‎/.y/‎ سيُطابِق "my" و "ay"، لكن ليس "yes" في الجملة "yes make my day".

‎\d مطابقة أيّ رقم (نظام الأرقام العربية المغربية). وهو يكافئ [‎0-9].

على سبيل المثال، التعبير ‎/\d/‎ أو /‎‎[0-9]‎/ سيُطابِق "2" في الجملة "B2 is the suite number".

‎\D مطابقة أيّ محرف ليس رقمًا (نظام الأرقام العربية المغربية). وهو يكافئ [‎0-9].

على سبيل المثال، التعبير ‎/\D/‎ أو /‎‎[^0-9]‎/ سيُطابِق "B" في الجملة "B2 is the suite number".

‎\w مطابقة أيّ محرف أو رقم (أي المحارف اللاتينية الأساسية مع الأرقام والشرطة السفلية). وهو يكافئ ‎[A-Za-z0-9_]‎.

على سبيل المثال، التعبير ‎/\w/‎ سيُطابِق "a" في "apple" و "5" في "‎$5.28" و "3" في "3D".

‎\W مطابقة أيّ محرف ليس من المحارف اللاتينية الأساسية مع الأرقام والشرطة السفلية. وهو يكافئ ‎[^A-Za-z0-9_]‎.

على سبيل المثال، التعبير ‎/\W/‎ سيُطابِق "%" في "50%‎‎‎".

‎\s مطابقة فراغ واحد، بما في ذلك المسافة العادية ومسافة الجدولة ومحرف الانتقال إلى سطرٍ جديد وغيرها، وهو يكافئ ‎[ ‎\f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]‎‎.

على سبيل المثال، التعبير ‎/\s\w*/‎ يُطابِق ‎" bar"‎ في "foo bar".

‎\S مطابقة أي محرف ما عدا الفراغات، بما في ذلك المسافة العادية ومسافة الجدولة ومحرف الانتقال إلى سطرٍ جديد وغيرها، وهو يكافئ ‎[^ ‎\f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]‎‎.

على سبيل المثال، التعبير ‎/\S\w*/‎ يُطابِق ‎"foo"‎ في "foo bar".

‎\t مطابقة مسافة الجدولة الأفقية.
‎\r مطابقة محرف العودة إلى بداية السطر (carriage return).
‎\n مُطابقة محرف الانتقال إلى سطرٍ جديد.
‎\f مطابقة محرف الانتقال إلى صفحة جديدة (form feed).
‎[\b]‎ مطابقة محرف الفراغ الخلفي (backspace، احذر الخلط بينه وبين ‎\b).
‎\0 مطابقة محرف NUL.
‎\cX حيث X هو محرف من A إلى Z، وهو يُطابِق محرف التحكم في سلسلة نصية.

على سبيل المثال، التعبير ‎/\cM/‎ يُطابِق control-M في سلسلة نصية.

‎\xhh مطابقة المحرف الذي له الرمز hh (رقمان بالنظام الست عشري).
‎\xhhhh مطابقة المحرف في ترميز UTF-16 الذي له الرمز hhhh (أربعة أرقام بالنظام الست عشري).
‎\u{hhhh}‎ أو ‎\u{hhhhh}‎ (يمكن استعمال هذه الأنماط عند ضبط الراية u فقط) مطابقة المحرف الذي له قيمة يونيكود U+hhhh أو U+hhhhh (أرقام في النظام الست عشري).
\ إذا استخدم مع المحارف العادية فسيُشير إلى أنَّ المحرف التالي له معنى خاص. فمثلًا التعبير /b/ يعني مطابقة الحرف "b"، لكن مع وضع خط مائل خلفي قبل الحرف "b" (أي سيصير التعبير ‎/\b/‎) فسيصبح للمحرف معنى خاص ألا وهو مطابقة حدود الكلمة.

وإذا استخدم مع المحارف الخاصة، فسيُشير إلى أنَّ المحرف التالي ليس له معنى خاص ويجب تفسير قيمته كما هي. فمثلًا المحرف "*" هو محرفٌ خاصٌ يعني مطابقة التعبير الذي يسبقه 0 مرة أو أكثر؛ أي أنَّ التعبير ‎/a*/‎ يعني مطابقة الحرف "a" لصفر مرة أو أكثر، أما لمطابقة رمز النجمة فسنضع خط مائل خلفي قبله، أي أنَّ التعبير ‎/a\*/‎ سيُطابِق "‎a*‎".

مجموعات المحارف

المجموعة المعنى
[xyz]

[a-c]

مجموعة محارف، وهي تُطابِق أي محرف من المحارف الموجودة داخلها، ويمكننا تحديد مجال باستخدام الشرطة، لكن إذا وجدتَ الشرطة كأول أو آخر حرف في المجموعة فستفسَّر على أنها شرطة عادية. من الممكن أيضًا تضمين فئات المحارف ضمن مجموعة محارف.

على سبيل المثال، التعبير [abcd] يكافئ [a-d]، وهو يُطابِق "b" في "brisket" و "c" في "chop".

على سبيل المثال، التعبير [abcd-] أو التعبير [-abcd] سيُطابِق "b" في"brisket" و "c" في "chop" و "-" في "non-profit".

[‎^xyz‎]

[‎‎^a-c]

مجموعة محارف مقلوبة (أو منفية)، أي أنَّها تُطابِق أي شيء ليس موجودًا بين قوسين.

على سبيل المثال، التعبير ‎[^abc]‎ يُماثِل ‎[^a-c]‎، وهو يطابِق "t" في "bat" و "h" في "chop".

الاختيار

المحرف المعنى
x|y مطابقة x أو y. على سبيل المثال، التعبير /green|red/ سيُطابِق "green" في "green apple" و "red" في "red apple".

الحدود

المحرف المعنى
^ مطابقة بداية المدخلات، وإذا كانت الراية m مضبوطةً فسيُطابِق ما بعد محرف الانتقال إلى سطرٍ جديدٍ مباشرةً.

على سبيل المثال، التعبير ‎/^A/‎ لن يُطابِق "A" في "an A" وإنما سيُطابِق أوّل "A" في "An A".

$ مطابقة نهاية المدخلات، وإذا كانت الراية m مضبوطةً فسيُطابِق ما قبل محرف الانتقال إلى سطرٍ جديدٍ مباشرةً.

على سبيل المثال، التعبير ‎/t$/‎ لن يُطابِق "t" في "eater" وإنما سيُطابِقها في "eat".

‎\b مطابقة حدود الكلمة، وهو المكان الذي لا يكون فيه أحد المحارف التي يمكن وجودها في الكلمات متبوعًا بمحرف يمكن وجوده في الكلمات مثل الفراغ أو حرف آخر.

أمثلة:

التعبير ‎/\bm/‎ يُطابِق "m" في "moon".

التعبير ‎/oo\b/‎ لا يطابِق "oo" في "moon" لأنَّ "oo" يتبعها "n" الذي هو حرف من محارف الكلمات.

التعبير ‎/oon\b/‎ يُطابِق "oon" في "moon" لأنَّ "oon" في نهاية السلسلة النصية، وبالتالي لن تكون متبوعةً بمحرفٍ من محارف الكلمات.

التعبير ‎/\w\b\w/‎ لن يطابِق أيّ شيء، لأنَّ محرفًا من محارف الكلمات لا يمكن أن يكون متبوعًا بمحرف ليس من محارف الكلمات ومحرف من محارف الكلمات في الوقت نفسه.

‎\B مطابقة ما ليس حدودًا للكلمات. وهو المكان الذي يكون فيه الحرف السابق والحرف التالي من نفس النوع: أي كلاهما من محارف الكلمات أو كلاهما ليسا من محارف الكلمات. مثل ما بين المحارف أو ما بين الفراغات.

على سبيل المثال، التعبير ‎/\Bon/‎ يُطابِق "on" في "at noon" والتعبير ‎/ye\B/‎ يُطابق "ye" في "possibly yesterday".

المجموعات

المحرف المعنى
(x) مطابقة النمط الفرعي x وحفظ هذا النمط. على سبيل المثال، النمط /(foo)/ يُطابِق "foo" في "foo bar" ويحتفظ بها.

تُرقَّم المجموعات بترتيب ورودها من اليسار بدءًا من 1، أيّ أنَّ السلاسل النصية الفرعية المُطابَقة من الأنماط الموجودة بين قوسين يمكن استدعاؤها من المصفوفة الناتج من ‎[1], ..., [n]‎ أو من خاصيات الكائن RegExp من ‎$1, ..., $9.

لاحظ أنَّ هذه الأقواس ستؤثر على الأداء، فإن لم تكن بحاجتها فاستخدم الأقواس التي لا تحتفظ بالقيم (انظر أدناه).

‎\n حيث n هو عددٌ صحيحٌ موجب، وهو إشارة إلى ما تمت مطابقته في النمط الفرعي (الموجود بين قوسين) الذي ترتيبه هو n (الترقيم يبدأ من 1 من اليسار).

على سبيل المثال، التعبير ‎/apple(,)\sorange\1/‎ يُطابِق ‎"apple, orange,"‎ في "apple, orange, cherry, peach". سنورد مثالًا معقدًا في ما يلي هذا الجدول.

(‎?:x) مطابقة النمط الفرعي x لكن دون تذكر ناتج المطابقة.

تحديد الكميات

المحرف المعنى
x*‎ مطابقة النمط الذي يسبقه 0 مرة أو أكثر.

مثلًا، التعبير ‎/bo*/‎ يُطابِق "boooo" في "A ghost booooed" و "b" في "A bird warbled"، ولن يطابِق أيّ شيء في "A goat grunted".

x+‎ مطابقة النمط الذي يسبقه مرة واحدة أو أكثر. وهو يماثل ‎{1,}‎.

مثلًا، التعبير ‎/a+/‎ يُطابِق "a" في "candy" و "aaaaaaa" في "caaaaaaandy".

x?‎ مطابقة النمط الذي يسبقه 0 مرة أو مرة واحدة فقط.

مثلًا، التعبير ‎/e?le?/‎ يُطابِق "el" في "angel" و "le" في "angle".

إذا استخدم هذا الرمز مباشرةً بعض أيّ مُحدِّد كميات (أي * و + و ? و {}) فسيجعل التحديد «غير جشع» (أي يُطابِق أقل كمية ممكنة من النص)، وذلك على النقيض من الحالة الافتراضية، وهي «التحديد الجشع» (مُطابَقة أكبر قدر ممكن من النص).

x{n}‎ مطابقة النمط x بعدد n مرة تحديدًا، إذ إنَّ n هو عدد صحيح موجب.

على سبيل المثال ‎/a{2}/‎ لا يطابِق "a" في "candy" لكنه يُطابِق "aa" في "caandy" وأوّل "aa" في "caaandy".

x{n,}‎ مطابقة النمط x بعدد n مرة على الأقل، إذ إنَّ n هو عدد صحيح موجب.

على سبيل المثال ‎/a{2,}/‎ لا يطابِق "a" في "candy" لكنه يُطابِق جميع محارف "a" في "caandy" و "caaaaaandy".

x{n,m}‎ مطابقة النمط x بعدد n مرة على الأقل و m مرة على الأكثر، إذ إنَّ n و m هما عددان صحيحان موجبان.

على سبيل المثال ‎/a{1,3}/‎ لا يطابق أيّ شيء في "cndy"، ويُطابِق "a" في "candy" ويطابق "aa" في "caandy" وأوّل 3 محارف "a" في "caaaaaaaaandy"، لاحظ أنَّه عند مطابقة السلسلة النصية "caaaaaaaaandy" كانت نتيجة المطابقة هي "aaa" مع أنَّ السلسلة النصية الأصلية فيها تكرارات أكثر لمحرف "a".

x*?‎

x+?‎

x??‎

x{n}?‎

x{n,}?‎

x{n,m}?‎

مطابقة أقل قدر ممكن من النص.

على سبيل المثال، النمط ‎/<.*?>/‎ يُطابِق "<foo>" في "<foo><bar>"،

بينما يطابق النمط ‎/<.*>/‎ السلسلة النصية كلها، أي "<foo> <bar>"

الخلاصة: مُحدِّدات الكميات تكون «جشعة» افتراضيًا، إلا إذا استخدمنا ? معها.

الشروط

المحرف المعنى
x(?=y)‎ مطابقة x إذا كانت x متبوعةً مباشرة بـ y.

على سبيل المثال، التعبير ‎/Jack(?=Sprat)/‎ يُطابِق "Jack" إذا كانت متبوعةً بالكلمة "Spart".

والتعبير ‎/Jack(?=Sprat|Frost)/‎ يُطابِق "Jack" إذا كانت متبوعةً بالكلمة "Spart" أو "Frost"؛ لكن انتبه إلى أنَّ "Spart" أو "Frost" لن تكونا جزءًا من السلسلة النصية المُطابَقة.

x(?!y)‎ مطابقة x إذا كانت x ليست متبوعةً بـ y.

على سبيل المثال، التعبير ‎/\d+(?!\.)/‎ يُطابِق الأعداد إذا لم تكن متبوعةً بفاصلة عشرية، فهو يطابِق "141" وليس "3.141".

الخاصيات التابعة للدالة البانية RegExp

RegExp.prototype

تسمح هذه الخاصية بإضافة خاصيات متاحة لجميع الكائنات التي نوعها هو RegExp.

RegExp.length

قيمة هذه الخاصية هي 2.

RegExp.lastIndex

الفهرس الذي سيبدأ البحث منه.

الدوال التابعة للدالة البانية RegExp

لا تملك الدالة البانية RegExp أيّة دوال تابعة لها، لكنها ترث بعض الدوال عبر سلسلة prototype كما هو مذكور في القسم التالي.

الكائن prototype

النسخ المُنشَأة من الدالة البانية RegExp ترث الدوال والخاصيات من كائن RegExp.prototype؛ وكما في جميع الدوال البانية، يمكنك إجراء تغييرات إلى كائن prototype في الدالة البانية لكي تنعكس تلك التعديلات إلى جميع نسخ الكائن RegExp.

لاحظ أنَّ عددًا من خاصيات الكائن RegExp لها أسماء طويلة وقصيرة (شبيهة بلغة Perl). كلا الاسمين يشير إلى القيمة نفسها. لغة Perl هي لغة برمجة استقت منها لغة JavaScript التعابير النمطية المستخدمة فيها.

الخاصيات

RegExp.prototype.constructor

تُحديد الدالة التي ستُنشِئ كائن prototype التابع للكائن RegExp؛ راجع صفحة الخاصية Object.prototype.constructor لمزيدٍ من التفاصيل.

RegExp.prototype.flags

سلسلة نصية تحتوي على الرايات المستخدمة في كائن RegExp.

RegExp.prototype.global

تحديد هل سيُختبَر التعبير النمطي على جميع المُطابقات الممكنة في السلسلة النصية، أم أنَّه سيتوقف بعد أوّل مطابقة.

RegExp.prototype.ignoreCase

تحديد هل سيتجاهل التعبير النمطي حالة الأحرف عند محاولة إجراء مطابقة في السلسلة النصية أم لا.

RegExp.prototype.multiline

تحديد هل سيجري التعبير النمطي مُطابقته على أكثر من سطر أم لا.

RegExp.prototype.source

نص التعبير النمطي.

RegExp.prototype.sticky

تحديد هل سيبدأ البحث من قيمة lastIndex أم لا.

RegExp.prototype.unicode

تحديد هل ستُفعّل ميزات يونيكود أم لا.

الدوال

RegExp.prototype.compile()‎

إعادة بناء التعبير النمطي أثناء تنفيذ السكربت، لم تكن هذه الدالة معياريةً، لكنها أضيفت إلى المعيار حديثًا، ولا ينصح باستخدامها، وإنما يُفتَرَض استخدام الدالة البانية RegExp.

RegExp.prototype.exec()‎

البحث عن نمط في السلسلة النصية المُعطاة، وإعادة النتائج.

RegExp.prototype.test()‎

التحقق من وجود النمط في السلسلة النصية المعطاة.

RegExp.prototype.[@@match]()‎

البحث عن نمط في السلسلة النصية المعطاة وإعادة ناتج المطابقة.

RegExp.prototype.[@@replace]()‎

البحث عن نمط في السلسلة النصية المعطاة وإعادة ناتج المطابقة.

RegExp.prototype.[@@search]()‎

البحث عن نمط في السلسلة النصية المعطاة وإعادة فهرس السلسلة النصية المُطابَقة.

RegExp.prototype.[@@split]()‎

تقسيم السلسلة النصية المعطاة إلى مصفوفة بفصلها إلى سلاسل نصية فرعية.

RegExp.prototype.toString()‎

إعادة سلسلة نصية تُمثِّل الكائن، وهي إعادة تعريف للدالة Object.prototype.toString.

أمثلة

استخدام التعابير النمطية لتغيير صيغة البيانات

السكربت الآتي يستخدم الدالة replace التابعة للكائن String لمطابقة الاسم بصيغة «الاسم الكنية» وتبديله إلى صيغة «الكنية، الاسم». وسنستخدم ‎$1 و ‎$2 للإشارة إلى السلاسل النصية التي تمت مطابقتها في الأنماط الفرعية:

var re = /(\w+)\s(\w+)/;
var str = 'Ahmed Mansor';
var newstr = str.replace(re, '$2, $1');
console.log(newstr); // "Mansor, Ahmed"

تعبير نمطي لتقسيم الأسطر

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

var text = 'Some text\nAnd some more\r\nAnd yet\rThis is the end';
var lines = text.split(/\r\n|\r|\n/);
console.log(lines); // [ 'Some text', 'And some more', 'And yet', 'This is the end' ]

استخدام تعبير نمطي على أكثر من سطر

var s = 'Please yes\nmake my day!';
s.match(/yes.*day/);
// null
s.match(/yes[^]*day/);
// ["yes\nmake my day"]

استخدام تعبير نمطي مع الراية "y"

الراية "y" تعني أنَّ التعبير النمطي سيحاول البدء بالمطابقة بدءًا من الفهرس المُشار إليه بالقيمة RegExp.prototype.lastIndex:

var str = '#foo#';
var regex = /foo/y;

regex.lastIndex = 1;
regex.test(str); // true
regex.lastIndex = 5;
regex.test(str); // false
regex.lastIndex; // 0 (إعادة ضبط قيمة الخاصية بعد فشل المطابقة)

استخراج اسم النطاق الفرعي من رابط URL

var url = 'http://xyz.domain.com';
console.log(/[^.]+/.exec(url)[0].substr(7)); // 'xyz'

التعابير النمطية ومحارف يونيكود

كما ذكرنا أعلاه، ستُطابِق ‎\w أو ‎\W محارف آسكي (ASCII) فقط، أي من a إلى z ومن A إلى Z ومن 0 إلى 9 و الشرطة السفلية _. ولمطابقة محارف اللغات الأخرى مثل العربية أو السيريلية، فاستخدم الصيغة ‎\uhhhh إذ إنَّ hhhh هي قيمة يونيكود للمحرف في نظام العد الست عشري. هذا المثال يشرح كيفية استخراج المحارف العربية من سلسلة نصية فيها كلام عربي وأجنبي:

var text = 'شيفرة javascript عن التعابير النمطية';
var regex = /[\u0600-\u06FF]+/g;

var match = regex.exec(text);
console.log(match[0]);        // 'شيفرة'
console.log(regex.lastIndex); // '5'

var match2 = regex.exec(text);
console.log(match2[0]);       // 'عن'
console.log(regex.lastIndex); // '19'

// وهكذا

يمكنك الحصول على مجالات محارف يونيكود لمختلف اللغات من الصفحة Regexp-unicode-block.

دعم المتصفحات

الميزة Chrome Firefox Internet Explorer Opera Safari
الدعم الأساسي نعم نعم نعم نعم نعم

انظر إلى صفحة كل خاصية ودالة تابعة للكائن RegExp لتفاصيل عن دعم المتصفحات لها.

مصادر ومواصفات