إنتقل إلى المحتوى الرئيسي

Regex ومطابقة الأنماط في Cursor: بناء الجملة ومجموعات الالتقاط والتوليد بمساعدة الذكاء الاصطناعي

Regex ومطابقة الأنماط في Cursor

التعبيرات النمطية (regex) هي طريقة مدمجة وقوية لمطابقة النص والتحقق منه واستخراجه. كما أنها صعبة القراءة بشهرة وسهولة الخطأ فيها. يجعل Cursor، وهو محرر IDE مدعوم بالذكاء الاصطناعي، العمل مع regex أسهل بكثير من خلال توليد الأنماط من أوصاف اللغة الطبيعية، وشرح التعبيرات المبهمة، واختبارها مقابل مدخلات نموذجية. يغطي هذا الدليل بناء جملة regex ومجموعات الالتقاط وتأكيدات lookahead و lookbehind وتوليد regex بمساعدة الذكاء الاصطناعي ومكتبة أنماط تحقق شائعة.

المتطلبات الأساسية​

قبل البدء، تأكد من توفر ما يلي:

  • Cursor (يُنصح بأحدث إصدار) كمحرر IDE الخاص بك
  • بيئة برمجة مع محرك regex (JavaScript أو Python أو Rust)
  • معرفة أساسية بمفاهيم معالجة السلاسل
تلميح

ذكاء Cursor الاصطناعي ممتاز في شرح وتوليد regex، لكنه ليس بديلاً عن فهم الأساسيات. راجع دائمًا الأنماط المُولّدة مقابل حالات الاختبار الخاصة بك، لأن محركات regex تختلف قليلاً بين اللغات. النمط الذي يعمل في JavaScript قد يتصرف بشكل مختلف في Python أو Rust.

أساسيات بناء جملة Regex​

فهم اللبنات الأساسية لـ regex يتيح لك قراءة وتصحيح أخطاء الأنماط بثقة. يمكن لـ Cursor شرح أي نمط، لكن معرفة المصطلحات تساعدك في كتابة طلبات أفضل.

الأحرف والأحرف الفوقية​

إليهم اللبنات الأساسية لـ regex:

البناءالمعنى
.أي حرف عدا السطر الجديد
\dرقم (0 إلى 9)
\wحرف كلمة (حرف، رقم، شرطة سفلية)
\sمسافة بيضاء (مسافة، tab، سطر جديد)
\D, \W, \Sالنسخ المنفية مما سبق
^بداية السلسلة (أو السطر في وضع multiline)
$نهاية السلسلة (أو السطر في وضع multiline)
\bحد الكلمة

المُكمّلات​

تتحكم المُكمّلات في عدد مرات تكرار الرمز:

المُكمّلالمعنى
*صفر أو أكثر
+واحد أو أكثر
?صفر أو واحد
{n}بالضبط n
{n,}n أو أكثر
{n,m}بين n و m

فئات الأحرف والبدائل​

تعرّف الأقواس المربعة مجموعة من الأحرف المسموح بها، ويُعرّف الأنبوب البدائل:

const vowelPattern = /[aeiou]/; // أي حرف متحرك واحد
const hexPattern = /[0-9a-fA-F]/; // أي رقم سداسي عشر
const colorPattern = /red|green|blue/; // واحدة من ثلاث كلمات

توليد أول نمط​

اطلب من Cursor توليد نمط من وصف:

اكتب regex يطابق رقم هاتف أمريكي بالصيغة (XXX) XXX-XXXX
حيث X رقم. أضف مجموعات التقاط مسماة لكود المنطقة
والرقم المحلي. اشرح كل جزء.

يُرجع Cursor النمط مع شرح:

// Pattern: /^\((?<areaCode>\d{3})\) (?<localNumber>\d{3}-\d{4})$/
const phonePattern = /^\((?<areaCode>\d{3})\) (?<localNumber>\d{3}-\d{4})$/;

const match = '(555) 123-4567'.match(phonePattern);
console.log(match.groups.areaCode); // "555"
console.log(match.groups.localNumber); // "123-4567"

يشرح Cursor: \( يطابق قوس فتح حرفي، \d{3} يطابق ثلاثة أرقام بالضبط، (?<areaCode>...) هو مجموعة التقاط مسماة، و \) يطابق قوس الإغلاق.

warning

الأقواس لها معنيان في regex: التجميع والالتقاط. للتجميع بدون التقاط، استخدم (?:...). نسيان ?: يُنشئ مجموعات التقاط غير ضرورية يمكن أن تُزحزح فهارس مجموعاتك وتسبب أخطاء خفية في الفهرسة عند فهرسة المجموعات بالرقم.

مجموعات الالتقاط والمراجع الخلفية​

تتيح لك مجموعات الالتقاط استخراج أجزاء من المطابقة وإعادة استخدامها لاحقًا في النمط. يُنشئ Cursor ويُحسّن مجموعات الالتقاط بدقة.

مجموعات الالتقاط المرقمة​

// استخراج مكونات التاريخ من YYYY-MM-DD
const datePattern = /(\d{4})-(\d{2})-(\d{2})/;
const match = '2025-08-17'.match(datePattern);
console.log(match[1]); // السنة: "2025"
console.log(match[2]); // الشهر: "08"
console.log(match[3]); // اليوم: "17"

مجموعات الالتقاط المسماة​

المجموعات المسماة أكثر قابلية للقراءة بكثير من المرقمة، خاصة في الأنماط الطويلة. اطلب من Cursor تحويل نمط:

حوّل هذا regex لاستخدام مجموعات التقاط مسماة بدلاً من المرقمة:
/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/

يعيد Cursor كتابته:

const isoPattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})T(?<hour>\d{2}):(?<minute>\d{2}):(?<second>\d{2})/;
const m = '2025-08-17T14:30:00'.match(isoPattern);
console.log(m.groups.year, m.groups.month, m.groups.day); // "2025" "08" "17"

المراجع الخلفية​

تتيح المراجع الخلفية للنمط مطابقة نفس النص الذي التقطته مجموعة سابقة. مثال كلاسيكي هو مطابقة الكلمات المتكررة:

// البحث عن كلمات مكررة مثل "the the"
const doubledWord = /\b(\w+)\s+\1\b/gi;
const text = 'I went to the the store and bought a a apple.';
console.log(text.replace(doubledWord, '$1'));
// "I went to the store and bought a apple."

يشير \1 إلى أي شيء طابقته مجموعة الالتقاط الأولى، لذلك ينجح النمط فقط عندما تكون الكلمة الثانية مطابقة للكلمة الأولى.

مجموعات عدم الالتقاط​

عندما تحتاج إلى تجميع للبدائل أو المُكمّلات لكنك لا تحتاج إلى النص الملتقط، استخدم مجموعة عدم التقاط لتجنب تلويث مصفوفة المطابقة:

// مطابقة "color" أو "colour" بدون التقاط "u" الاختياري
const colorPattern = /colou?r/;
const ukPattern = /col(?:ou)?r/; // متغير عدم التقاط
تلميح

اطلب من Cursor تدقيق regex معقد للبحث عن مجموعات التقاط غير ضرورية. اطلب: "ابحث عن مجموعات التقاط في هذا النمط غير المستخدمة وحوّلها إلى مجموعات عدم التقاط." المجموعات الأنظف تجعل كودك أكثر قابلية للتنبؤ وأسرع قليلاً.

Lookahead و Lookbehind​

Lookahead و lookbehind هي تأكيدات بعرض صفر تتحقق من السياق دون استهلاك أحرف. وهي ضرورية للتحقق بدون استخراج.

Lookahead الإيجابي​

يؤكد lookahead الإيجابي (?=...) أن ما يلي يطابق دون تضمينه في النتيجة. استخدام شائع هو التحقق من كلمة المرور:

// 8 أحرف على الأقل، حرف كبير واحد، رقم واحد
const strongPassword = /^(?=.*[A-Z])(?=.*\d).{8,}$/;
console.log(strongPassword.test('Abcdefg1')); // true
console.log(strongPassword.test('password')); // false

كل (?=...) يتحقق من شرط من بداية السلسلة، ثم .{8,} يطابق أحرف كلمة المرور الفعلية.

Lookahead السلبي​

يؤكد lookahead السلبي (?!...) أن ما يلي لا يطابق:

// مطابقة "java" غير متبوعة بـ "script"
const javaNotScript = /\bjava(?!script)\b/i;
console.log(javaNotScript.test('I love java')); // true
console.log(javaNotScript.test('I love javascript')); // false

Lookbehind الإيجابي والسلبي​

يتحقق lookbehind (?<=...) و (?<!...) مما يسبق الموضع الحالي. استخدمها لاستخراج المطابقات المعتمدة على السياق:

// استخراج المبالغ بالدولار بعد علامة $
const pricePattern = /(?<=\$)\d+(\.\d{2})?/g;
console.log('$19.99 and $5'.match(pricePattern)); // ["19.99", "5"]

// مطابقة "cat" غير مسبوقة بـ "wild "
const domesticCat = /(?<!wild )cat\b/;
console.log(domesticCat.test('my cat')); // true
console.log(domesticCat.test('a wild cat')); // false
warning

دعم lookbehind يختلف بين المحركات. أضاف JavaScript lookbehind في ES2018، لذا ترفض المتصفحات وبيئات التشغيل الأقدم الأنماط ذات (?<=...). لا تدعم crate regex الخاصة بـ Rust lookbehind على الإطلاق. إذا كنت تستهدف Rust، اطلب من Cursor إعادة كتابة أنماط lookbehind بدونه، عادةً بالتقاط السياق السابق في مجموعة.

توليد أنماط حساسة للسياق​

اطلب من Cursor بناء نمط مع تأكيدات:

اكتب regex يطابق كل كلمة في جملة ما عدا الكلمات "the"
و "a" و "an". استخدم lookahead السلبي وحدود الكلمات.
قدم حالات اختبار.

يُرجع Cursor:

const contentWord = /\b(?!the\b|a\b|an\b)\b[a-z]+/gi;
const sentence = 'the quick brown fox jumps over a lazy dog';
console.log(sentence.match(contentWord));
// ["quick", "brown", "fox", "jumps", "over", "lazy", "dog"]

توليد Regex بمساعدة الذكاء الاصطناعي​

القدرة البارزة لـ Cursor هي تحويل متطلبات اللغة الطبيعية إلى regex مُختبَر. يُظهر هذا القسم تدفقات عمل عملية.

التوليد من المواصفات​

صف قواعد المطابقة بالتفصيل، بما في ذلك الحالات الحدية:

ولّد regex يتحقق من سلسلة إصدار semver مع علامة ما قبل
الإصدار الاختيارية. المتطلبات:
- Major و minor و patch أعداد صحيحة غير سالبة بدون أصفار بادئة
- ما قبل الإصدار اختياري، مفصول بشرطة
- ما قبل الإصدار يمكن أن يحتوي على معرفات أبجدية رقمية مفصولة بنقاط
- أمثلة: 1.0.0, 2.14.3-alpha, 3.0.0-beta.1, 0.0.1-rc.2.exp
- غير صالح: 01.0.0, 1.0, 1.0.0-, 2.x.3

يُنتج Cursor نمطًا مشروحًا جيدًا:

// Major: 0 or [1-9]\d*
// Minor and Patch: same as Major
// Prerelease: -(identifier)(.identifier)* where identifier = [0-9A-Za-z-]+
const semverPattern = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/;

const tests = [
['1.0.0', true],
['2.14.3-alpha', true],
['3.0.0-beta.1', true],
['0.0.1-rc.2.exp', true],
['01.0.0', false],
['1.0', false],
['1.0.0-', false],
['2.x.3', false],
];

tests.forEach(([input, expected]) => {
console.log(input, semverPattern.test(input) === expected ? 'PASS' : 'FAIL');
});

شرح الأنماط المبهمة​

الصق regex وجدته على الإنترنت واطلب من Cursor شرحه:

اشرح هذا regex وأعد كتابته مع تعليقات ومجموعات مسماة:
/^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/

يُفككه Cursor:

// مدقق عنوان IPv4
// كل ثُماني يطابق: 0-9 | 00-99 | 100-199 | 200-249 | 250-255
const octet = '(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)';
const ipv4Pattern = new RegExp(`^(?:${octet}\\.){3}${octet}$`);

// مع مجموعات مسماة للقراءة
const ipv4Named = /^(?<o1>25[0-5]|2[0-4]\d|[01]?\d\d?)\.(?<o2>25[0-5]|2[0-4]\d|[01]?\d\d?)\.(?<o3>25[0-5]|2[0-4]\d|[01]?\d\d?)\.(?<o4>25[0-5]|2[0-4]\d|[01]?\d\d?)$/;
const m = '192.168.1.1'.match(ipv4Named);
console.log(m.groups); // { o1: "192", o2: "168", o3: "1", o4: "1" }

يشرح Cursor أن 25[0-5] يطابق 250 إلى 255، 2[0-4]\d يطابق 200 إلى 249، و [01]?\d\d? يطابق 0 إلى 199.

تصحيح أخطاء الأنماط الفاشلة​

عندما لا يطابق regex كما هو متوقع، صِف المشكلة:

regex الخاص بي /^\d{4}-\d{2}-\d{2}$/ يجب أن يطابق "2025-08-17"
لكن دالتي تُرجع null. إليك كودي. ابحث عن الخطأ.

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

أنماط تحقق شائعة​

يمكن لـ Cursor توليد مكتبة قابلة لإعادة الاستخدام من الأنماط المُتحقَّق منها. إليك مجموعة عملية.

التحقق من البريد الإلكتروني​

// تحقق عملي من البريد الإلكتروني (regex المتوافق تمامًا مع RFC 5322 غير عملي)
const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
console.log(emailPattern.test('[email protected]')); // true
console.log(emailPattern.test('invalid@@test')); // false
تلميح

لا تتحقق بشكل مفرط من عناوين البريد الإلكتروني باستخدام regex. التحقق الموثوق الوحيد هو إرسال بريد إلكتروني للتأكيد. استخدم regex متساهلاً لالتقاط الأخطاء المطبعية الواضحة، ثم تحقق من قابلية التسليم. اطلب من Cursor: "اكتب regex بريد إلكتروني متساهل ودالة تتحقق أيضًا من وجود سجل MX،" لنهج متوازن.

التحقق من URL​

const urlPattern = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)$/;
console.log(urlPattern.test('https://www.example.com/path?q=1')); // true

التحقق من Slug​

// slug آمن لـ URL: أحرف صغيرة، أرقام، شرطات، بدون شرطة بادئة أو لاحقة
const slugPattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
console.log(slugPattern.test('how-to-use-cursor')); // true
console.log(slugPattern.test('-invalid-slug')); // false

لون سداسي عشري​

// سداسي عشري 3 أو 6 أرقام مع # اختيارية
const hexPattern = /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
console.log(hexPattern.test('#fff')); // true
console.log(hexPattern.test('FF5733')); // true

كلمة مرور قوية​

// 8 أحرف على الأقل، حرف كبير واحد، حرف صغير، رقم، ورمز
const passwordPattern = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^A-Za-z0-9]).{8,}$/;
console.log(passwordPattern.test('Curs0r!de')); // true

الاستخراج والاستبدال النصي​

regex ليس فقط للتحقق؛ بل يتفوق في الاستخراج والتحويل.

استخراج جميع المطابقات​

// استخراج جميع الوسوم من منشور شبكة اجتماعية
const hashtagPattern = /#[\w]+/g;
const post = 'Loving #Cursor IDE and #regex today! #coding';
console.log(post.match(hashtagPattern)); // ["#Cursor", "#regex", "#coding"]

التحويل مع Replace ومجموعات الالتقاط​

// تحويل kebab-case إلى camelCase
const kebabToCamel = /-([a-z])/g;
const result = 'font-size-in-cursor'.replace(kebabToCamel, (_, c) => c.toUpperCase());
console.log(result); // "fontSizeInCursor"

القوالب مع المجموعات المسماة​

// استبدال العناصر النائبة {{ var }} بقيم من كائن سياق
const templatePattern = /{{\s*(?<key>\w+)\s*}}/g;
function render(template, context) {
return template.replace(templatePattern, (_, key) => context[key] ?? '');
}
console.log(render('Hello {{ name }}, you have {{ count }} tasks', { name: 'Sam', count: 3 }));
// "Hello Sam, you have 3 tasks"
warning

دالة استبدال regex تشغّل الاستبدال لكل مطابقة. إذا كان كائن السياق الخاص بك كبيرًا وقالبك في مسار ساخن، فجمّع النمط مسبقًا وخزّن بحث السياق مؤقتًا. احمِ أيضًا من قيم undefined لتجنب ظهور السلسلة الحرفية "undefined" في مخرجاتك.

الأداء والسلامة​

regex المكتوب بشكل سيء يمكن أن يسبب تتبعًا خلفيًا كارثيًا، حيث يستغرق المحرك وقتًا أسيًا في مدخلات معينة. هذا خطر أمني حقيقي (ReDoS).

اكتشاف التتبع الخلفي الكارثي​

اطلب من Cursor تحليل نمط:

تحقق من هذا regex لخطر التتبع الخلفي الكارثي (ReDoS)
وأعد كتابته بأمان: /^(a+)+$/

يشرح Cursor أن المُكمّلات المتداخلة مثل (a+)+ تُنشئ تتبعًا خلفيًا أسيًا في مدخلات مثل aaaaaaaaaaaaaaaaaaaa!، ثم يوفر بديلاً آمنًا:

// بديل آمن: مُكمّل واحد مثبت
const safePattern = /^a+$/;

استخدام المراسي والمجموعات الذرية​

ثبّت الأنماط دائمًا عندما تتوقع مطابقة السلسلة الكاملة. عند الدعم، استخدم المجموعات الذرية (?>...) لمنع التتبع الخلفي:

// مكافئ المُكمّل التملكي في JS (لا دعم أصلي، استخدم حيلة lookahead)
const possessiveDigit = /(?=(\d++))\1/;
تلميح

للمدخلات غير الموثوقة، عيّن دائمًا مهلة على تنفيذ regex أو استخدم مكتبة تدعم التنفيذ المحدود. اطلب من Cursor: "أضف غلاف مهلة إلى دالة اختبار regex الخاصة بي باستخدام Web Worker،" لمنع إدخال خبيث من تجميد تطبيقك.

ملخص أفضل الممارسات​

ضع هذه المبادئ في الاعتبار عند العمل مع regex في Cursor:

  • افضل مجموعات الالتقاط المسماة على المرقمة للقراءة.
  • استخدم مجموعات عدم الالتقاط (?:...) عندما لا تحتاج إلى النص الملتقط.
  • ثبّت أنماطك بـ ^ و $ عند التحقق من سلاسل كاملة.
  • اهرب الأحرف الخاصة عند إقحام مدخلات المستخدم في نمط.
  • اختبر مقابل الحالات الإيجابية والسلبية لالتقاط الحالات الحدية.
  • احذر التتبع الخلفي الكارثي في الأنماط ذات المُكمّلات المتداخلة.
  • أضف تعليقات للأنماط المعقدة باستخدام علم x أو المجموعات المسماة.

من خلال الجمع بين أساسيات regex المتينة والتوليد والشرح المدعوم بالذكاء الاصطناعي في Cursor، يمكنك كتابة واختبار وصيانة كود مطابقة الأنماط بثقة. صِف نيتك بوضوح، ودع Cursor يُنتج ويشرح النمط، ثم تحقق منه ضد مجموعة شاملة من حالات الاختبار قبل الشحن.