مقالات

راهنمای جامع dو Dدر Regex: استخراج اعداد و فیلتر کردن غیر-اعداد

راهنمای جامع dو Dدر Regex: استخراج اعداد و فیلتر کردن غیر-اعداد

سلام! من سارا بحرانی‌ام، کارشناس سئو از تیم «وزیر سئو». اگه تا حالا موقع اعتبارسنجی یه فرم ثبت‌نام یا تمیز کردن شماره تلفن‌ها با عبارات باقاعده (Regex) سروکله زدی، حتماً چشمت به d خورده. این دستور کوچیک ولی فوق‌العاده قدرتمند، یکی از پرکاربردترین ابزارها توی جعبه‌ابزار ماست.

d و جفت دقیقاً مخالفش یعنی D، جزو معروف‌ترین کلاس های کاراکتری (Character Classes) هستن که به جای نوشتن دستورات طولانی، به ما میان‌برهای سریع و خوانا می‌دن.

توی این راهنمای کامل، می‌خوام بهت یاد بدم d دقیقاً چیه، چطور ازش برای استخراج و اعتبارسنجی اعداد استفاده کنی، و چطور با D داده‌هات رو مثل آب خوردن پاکسازی کنی. حتی می‌ریم سراغ نکته تخصصی اعداد فارسی! آماده‌ای؟

جدول کاربردی: مقایسه سریع d، D و [0-9]

قبل از اینکه عمیق بشیم، بذار یه خلاصه‌ی سریع بهت بدم تا دید کلی پیدا کنی:

دستور (Pattern) معنی چه چیزی را تطبیق می‌دهد؟ چه چیزی را تطبیق نمی‌دهد؟
d یک رقم عددی ‘7’، ‘0’ (و در موتورهای مدرن، ‘۳’ فارسی) ‘a’، ‘+’، ‘ ‘ (فاصله)
D یک کاراکتر غیر عددی ‘a’، ‘+’، ‘ ‘ (فاصله)، ‘؟’ ‘7’، ‘0’ (و در موتورهای مدرن، ‘۳’ فارسی)
[0-9] فقط یک رقم انگلیسی ‘7’، ‘0’ ‘a’، ‘+’، ‘ ‘، ۳ (فارسی)

d چیست؟ (میان‌بُر کلاس کاراکتر اعداد)

توی دنیای رجکس، ما یه سری “کلاس کاراکتر” (Character Classes) داریم. این‌ها میان‌برهایی هستن که به جای نوشتن چند کاراکتر مختلف، از یه نماد خاص استفاده می‌کنیم.

d (که مخفف digit به معنی “رقم” هست) دقیقاً همین کاره. به زبان ساده، d به موتور رجکس می‌گه: «دنبال هر کاراکتر عددی بگرد.»

تعریف فنی: d به عنوان معادل دقیق [0-9]

اگه بخوایم فنی‌تر صحبت کنیم، d یه نام مستعار یا میان‌بر دقیق برای [0-9] هست.

عبارت [0-9] (کلاس کاراکتری که شامل اعداد 0 تا 9 می‌شه) به موتور رجکس می‌گه “یکی از کاراکترهای داخل براکت رو پیدا کن”. استفاده از d دقیقاً همین معنی رو می‌ده، اما خیلی خواناتر و کوتاه‌تره.

به‌جای اینکه بنویسی [0123456789] (که طولانیه) یا [0-9] (که کوتاه‌تره)، خیلی ساده می‌نویسی d. هر دوتاشون برای موتور رجکس یه معنی دارن.

d چه چیزهایی را تطبیق می‌دهد؟ (اعداد ۰ تا ۹)

این یه نکته خیلی مهمه که باید حواست باشه. d فقط و فقط یک رقم (digit) رو تطبیق می‌ده. فرقی نمی‌کنه این رقم ‘0’، ‘5’ یا ‘9’ باشه.

اگه توی رشته‌‌ای مثل ‘abc123xyz’ از d استفاده کنی، اولین چیزی که پیدا می‌کنه ‘1’ هست. اگه دوباره جستجو رو ادامه بدی، ‘2’ رو پیدا می‌کنه و بعدش ‘3’.

اما d به‌تنهایی هیچ‌وقت ‘123’ رو با هم پیدا نمی‌کنه، چون وظیفه‌اش پیدا کردن یک رقم در لحظه‌ است.

مثال ساده: پیدا کردن اولین عدد در یک رشته

فرض کن یه رشته (string) مثل این داری: “کد پستی شما: 14589-331 است”. حالا می‌خوای اولین رقمی که توی این متن وجود داره رو پیدا کنی.

رشته: کد پستی شما: 14589-331 است

الگوی رجکس: d

نتیجه: اولین چیزی که پیدا می‌شه، کاراکتر ‘1’ هست.

اگه جستجو رو ادامه بدی (مثلاً با فلگ g یا global)، به ترتیب ‘4’، ‘5’، ‘8’، ‘9’، ‘3’، ‘3’، و ‘1’ رو هم پیدا می‌کنه.

استفاده از d+: چگونه اعداد چند رقمی (مانند ۱۲۳) را تطبیق دهیم؟

خب، حالا می‌رسیم به سوال اصلی: اگه نخوایم فقط ‘1’ رو پیدا کنیم و بخوایم کل عدد ‘14589’ رو یک‌جا بکشیم بیرون چی؟ اینجا پای “تکرارکننده‌ها” یا Quantifiers به وسط میاد.

علامت + (پلاس) توی رجکس یعنی: «یک یا چند بار تکرار شو».

وقتی تو d (یک رقم) رو با + ترکیب می‌کنی و می‌نویسی d+، معنیش این می‌شه: «دنبال رشته‌ای بگرد که از یک یا چند رقم پشت سر هم تشکیل شده باشه.»

مثال قبلی رو دوباره ببینیم:

رشته: کد پستی شما: 14589-331 است

الگوی رجکس: d+

نتیجه اول: 14589

نتیجه دوم (اگه ادامه بدیم): 331

دیدی چقدر راحت شد؟ d+ تمام اعداد چند رقمی رو برات پیدا می‌کنه و دیگه کاری به حروف یا خط تیره (-) نداره.

D چیست؟ (میان‌بُر کلاس کاراکتر غیر-اعداد)

به ساده‌ترین زبان ممکن، D (که با D بزرگ نوشته می‌شه) دقیقاً برعکس d عمل می‌کنه.

در حالی که d دنبال هر رقم عددی می‌گشت، D به موتور رجکس می‌گه: «دنبال هر کاراکتری بگرد که عدد نیست

این دستور برای وقت‌هایی عالیه که می‌خوای همه‌چیز رو پیدا کنی به‌جز اعداد. مثلاً می‌خوای حروف یا نمادها رو از یه رشته که قاطی با عدده جدا کنی.

تعریف فنی: D به عنوان معادل [^0-9]

از نظر فنی، D یک میان‌بر دقیق برای عبارت [^0-9] هست.

بذار این عبارت رو برات باز کنم:

[…] یعنی یک “کلاس کاراکتر” (Character Class).

0-9 یعنی همه‌ی ارقام از ۰ تا ۹.

علامت ^ (کلاه یا Caret) وقتی درست در ابتدای یک کلاس کاراکتر میاد، معنی “نفی” (Negation) می‌ده.

پس [^0-9] یعنی: «هر کاراکتری رو پیدا کن که در محدوده 0 تا 9 نباشه.» D دقیقاً همین کار رو به شکلی کوتاه‌تر و خواناتر انجام می‌ده.

D چه چیزهایی را تطبیق می‌دهد؟ (حروف، نمادها، فاصله‌ها)

خب، وقتی می‌گیم “هر چیزی که عدد نیست”، منظورمون دقیقاً چیه؟ D یه طیف خیلی گسترده‌ای از کاراکترها رو شامل می‌شه:

حروف الفبا: چه انگلیسی (a-z, A-Z) و چه فارسی (ا، ب، پ، …)

نمادها و علائم نگارشی: مثل !، @، #، $، &، *، . (نقطه)، – (خط تیره)، _ (آندرلاین) و…

فاصله‌ها (Whitespace): این خیلی مهمه! D شامل فاصله خالی (space)، تب (tab) و حتی کاراکتر خط جدید (newline) هم می‌شه.

مثال: فرض کن این رشته رو داریم: کد: 123-ABC!

اگه از D استفاده کنیم، اولین چیزی که پیدا می‌کنه چیه؟ ‘ک’

اگه ادامه بدیم: ‘د’، ‘:’، ‘ ‘ (فاصله)، – (خط تیره)، ‘A’، ‘B’، ‘C’ و ‘!’.

تنها چیزهایی که D نادیده می‌گیره، ‘1’، ‘2’ و ‘3’ هستن.

رابطه معکوس: چرا D دقیقاً مخالف d است؟

این دوتا مثل شب و روز یا مثبت و منفی هستن. هر کاراکتری در دنیا یا d هست یا D. هیچ حد وسطی وجود نداره.

d (digit): فقط [0-9]

D (non-digit): فقط [^0-9]

اون‌ها مجموعه‌های مکمل همدیگه هستن. d فقط اعداد رو می‌گیره و D هر چیزی غیر از اون اعداد رو می‌گیره.

این ویژگی توی رجکس خیلی رایجه. مثلاً ما w (برای حروف و اعداد) و W (برای غیر حروف و اعداد) یا s (برای فاصله‌ها) و S (برای غیر فاصله‌ها) رو هم داریم. این جفت‌های معکوس ابزارهای خیلی قدرتمندی برای تمیزکاری و اعتبارسنجی داده‌ها بهت می‌دن.

کاربردهای عملی d: استخراج و اعتبارسنجی

به‌طور کلی، ما از d برای دو تا کار اصلی استفاده می‌کنیم: ۱. استخراج داده (Extraction): وقتی می‌خوایم اعداد رو از وسط یه متن شلوغ بیرون بکشیم. ۲. اعتبارسنجی (Validation): وقتی می‌خوایم مطمئن شیم که ورودی کاربر (مثلاً توی یه فرم) فقط شامل اعداد با یه فرمت خاصه.

بریم هر کدوم رو با مثال ببینیم.

کاربرد اول: استخراج تمام اعداد از یک متن (Data Extraction)

فرض کن یه متن طولانی داری و می‌خوای همه‌ی قیمت‌ها، تعداد موجودی‌ها یا شناسه‌ها رو از توش دربیاری. اینجا d به کمکت میاد. البته، همونطور که قبلاً گفتیم، ما معمولاً از d+ استفاده می‌کنیم تا اعداد چند رقمی رو هم کامل بگیریم.

مثال: فرض کن این متن رو از یه صفحه محصول کپی کردی: “قیمت این کالا 1,500,000 تومان است. موجودی انبار: 42 عدد. شناسه محصول: 987-654”

اگه تو بخوای فقط اعداد رو از این متن بکشی بیرون، کافیه از الگوی d+ استفاده کنی.

رشته: “قیمت این کالا 1,500,000 تومان است. موجودی انبار: 42 عدد. شناسه محصول: 987-654”

الگوی رجکس: d+

پرچم (Flag): باید از g (گلوبال) استفاده کنی تا جستجو بعد از اولین پیدا کردن متوقف نشه.

نتیجه (لیست اعداد استخراج شده):

1

500

000

42

987

654

نکته مهم: همونطور که می‌بینی، 1,500,000 رو به سه تیکه تقسیم کرد، چون کاما (,) عدد نیست و جزو d حساب نمی‌شه. اگه می‌خواستی خود کاماها رو هم مدیریت کنی، باید الگوی پیچیده‌تری می‌نوشتی. اما برای استخراج ساده‌ی اعداد، d+ عالی عمل می‌کنه.

کاربرد دوم: اعتبارسنجی فرم‌ها (مثلاً کد پستی یا سن)

این یکی از مهم‌ترین کاربردهای رجکسه. وقتی کاربر توی یه فرم ثبت‌نام چیزی وارد می‌کنه، تو باید مطمئن بشی که ورودی درسته.

مثال ۱: اعتبارسنجی سن می‌خوای مطمئن بشی کاربر سنی بین ۱ تا ۳ رقم وارد کرده (مثلاً “۸” یا “۲۵” یا “۱۱۰”).

الگوی رجکس: d{1,3}

توضیح: {1,3} یه “تکرارکننده” (Quantifier) هست که می‌گه “بین ۱ تا ۳ بار تکرار شو”. پس این الگو با “5” و “99” و “101” مطابقت داره، ولی با “1000” نه.

مثال ۲: اعتبارسنجی کد پستی فرض کن می‌خوای مطمئن بشی کاربر دقیقاً یه کد پستی ۵ رقمی وارد کرده.

الگوی رجکس: d{5}

توضیح: {5} یعنی “دقیقاً ۵ بار تکرار شو”. این الگو با “12345” مطابقت داره، ولی با “1234” یا “123456” نه.

اما یه مشکل بزرگ این وسط وجود داره که ما رو می‌رسونه به بخش بعدی…

تفاوت حیاتی بین d و ^d+$ برای اعتبارسنجی

این یه اشتباه رایجه که خیلی‌ها اول کار می‌کنن. فرض کن همون فیلد کد پستی ۵ رقمی رو داری و از الگوی d{5} برای اعتبارسنجی استفاده می‌کنی.

سناریوی فاجعه‌بار:

الگوی تو: d{5}

ورودی کاربر: “کد پستی من 12345 است”

نتیجه اعتبارسنجی: تایید می‌شه! (Match)

چرا؟ چون موتور رجکس می‌گرده و می‌بینه که رشته‌ی 12345 (که ۵ تا رقم پشت همه) داخل اون متن وجود داره. الگوی تو نگفته “کل متن باید این باشه”، فقط گفته “بگرد این الگو رو پیدا کن”.

راه حل صحیح: استفاده از انکرها (Anchors) برای اعتبارسنجی کل رشته، باید از دوتا کاراکتر جادویی دیگه استفاده کنی: ^ و $

^ (کلاه): یعنی “شروع رشته”. به موتور رجکس می‌گه “الگو باید از همون اول رشته شروع بشه”.

$ (دلار): یعنی “پایان رشته”. به موتور رجکس می‌گه “الگو باید دقیقاً آخر رشته تموم بشه”.

حالا الگوی اعتبارسنجی کد پستی رو بازنویسی می‌کنیم:

الگوی صحیح: ^d{5}$

ترجمه: “از ابتدای رشته (^) تا انتهای رشته ($)، باید دقیقاً ۵ رقم (d{5}) وجود داشته باشه و نه هیچی بیشتر یا کمتر.”

حالا نتایج رو ببین:

ورودی: “12345” -> تایید می‌شه (Match)

ورودی: “1234” -> رد می‌شه (No Match) (چون ۵ تا نیست)

ورودی: “123456” -> رد می‌شه (No Match) (چون ۵ تا نیست)

ورودی: “abc12345” -> رد می‌شه (No Match) (چون با ^ شروع نشده)

ورودی: “12345abc” -> رد می‌شه (No Match) (چون به $ ختم نشده)

قانون طلایی: هر وقت خواستی یه ورودی فرم رو اعتبارسنجی کنی و مطمئن بشی کل ورودی با الگوت می‌خونه، همیشه الگوت رو بین ^ و $ بذار.

کاربردهای عملی D: پاکسازی و جداسازی داده‌ها

وقتی با داده‌هایی سروکار داری که از کاربر گرفتی یا از جایی کپی کردی، معمولاً پر از کاراکترهای اضافی، فاصله‌ها، حروف و نمادهاییه که تو نمی‌خوای. D ابزار اصلی تو برای خلاص شدن از شر همه‌ی ایناست.

کاربرد اول: پاکسازی شماره تلفن (حذف پرانتز، خط تیره و حروف)

این کلاسیک‌ترین و شاید مهم‌ترین کاربرد D هست. کاربرا شماره تلفن رو به هزار شکل مختلف وارد می‌کنن:

(021) 8877-6655

0912 123 45 67

+98 (912) 123-4567

0912-abc-1234 (ورودی اشتباه)

اگه بخوای این‌ها رو توی دیتابیس ذخیره کنی یا به یه API بفرستی، فاجعه می‌شه. تو یه فرمت استاندارد و تمیز می‌خوای، مثل: 02188776655 یا 09121234567.

راه حل جادویی: اینجا ما از قابلیت جستجو و جایگزینی” (Search and Replace) در رجکس استفاده می‌کنیم.

الگو (Search): D (یا D+ که یعنی یک یا چند کاراکتر غیر عددی پشت سر هم)

جایگزین (Replace with): “” (یعنی هیچی یا یک رشته‌ی خالی)

نتیجه چی می‌شه؟ موتور رجکس می‌گرده و هرچیزی که عدد نیست (پرانتز، فاصله، خط تیره، علامت +، و حتی اون abc اشتباهی) رو پیدا می‌کنه و با “هیچی” جابه‌جا می‌کنه.

+98 (912) 123-4567 تبدیل می‌شه به 989121234567.

(021) 8877-6655 تبدیل می‌شه به 02188776655.

به همین سادگی تو یه داده‌ی تمیز و یکدست داری!

کاربرد دوم: جداسازی (Split) یک رشته بر اساس اعداد

این H3 یه کم گمراه‌کننده است. ما معمولاً رشته رو “بر اساس اعداد” (یعنی با d+) نمی‌شکنیم، مگه اینکه بخوایم متن‌ها رو جدا کنیم.

اما اگه بخوایم از D استفاده کنیم (که موضوع این بخشه)، می‌تونیم برعکس عمل کنیم: یعنی رشته رو بر اساس هرچیزی که عدد نیست (D+) بشکنیم تا فقط اعداد برامون باقی بمونن.

مثال: فرض کن یه رشته‌ی نامرتب از شناسه‌های محصول داری: “شناسه: 12345 (موجود) | شناسه: 67890 (ناموجود)”

تو فقط خود شناسه‌ها (12345 و 67890) رو می‌خوای. می‌تونی از تابع Split زبانت استفاده کنی و بگی رشته رو بر اساس D+ بشکنه.

رشته: “ID: 12345 (OK), ID: 67890 (FAIL)”

شکستن بر اساس (Split by): D+

نتیجه (به صورت لیست): [“”, “12345”, “67890”]

(اون “” اولی به خاطر اینه که رشته با یه D شروع شده). با یه فیلتر ساده، تو یه لیست تمیز از اعدادت داری.

کاربرد سوم: یافتن خطاهایی که نباید حاوی عدد باشند

این یه نکته‌ی خیلی مهمه که باید بهش دقت کنی. عنوان این بخش در مورد D هست، اما برای این کاربرد خاص، ما دقیقاً برعکس عمل می‌کنیم و از d کمک می‌گیریم! بذار توضیح بدم.

فرض کن یه فیلد “نام” یا “نام خانوادگی” توی فرم داری. تو انتظار داری که این فیلدها فقط حاوی حروف باشن (یعنی کاراکترهای D، هرچند D شامل نمادها هم می‌شه که بازم خوب نیست، ولی فعلاً فرض کنیم فقط عدد نباید باشه).

حالا می‌خوای مطمئن بشی کاربر اشتباهی عدد وارد نکرده باشه.

سناریوی اعتبارسنجی:

فیلد: نام خانوادگی

ورودی کاربر: “بحرانی”

ورودی کاربر: “بحرانی 123”

برای پیدا کردن این خطا، تو باید دنبال چی بگردی؟ دنبال اون 123. و ابزار پیدا کردن 123 چیه؟ d!

پس قانون اینه: برای اعتبارسنجی فیلدی که نباید عدد داشته باشه (مثل فیلد نام)، تو از d استفاده می‌کنی. اگه الگوی d حتی یک نتیجه هم برگردونه، یعنی ورودی کاربر نامعتبر (Invalid) هست.

چک کردن بحرانیبا الگوی d: نتیجه‌ای نداره (No Match). پس ورودی معتبره.

چک کردن بحرانی 123با الگوی d: نتیجه برمی‌گردونه (Match Found). پس ورودی نامعتبره.

پس اینجا ما از d استفاده می‌کنیم تا مطمئن شیم که کل رشته باید D می‌بوده.

چالش‌های پیشرفته: d، یونیکد و اعداد فارسی (نکته تخصصی)

وقتی ما توی ایران از «عدد» حرف می‌زنیم، منظورمون می‌تونه 123 باشه یا ۱۲۳. این دوتا برای ما یه معنی دارن، اما برای کامپیوتر دوتا کاراکتر کاملاً متفاوت هستن. d توی دنیای مدرن رجکس باید با این قضیه کنار بیاد، و اینجاست که داستان یه کم پیچیده می‌شه.

تفاوت d و [0-9] در موتورهای Regex مدرن (ASCII vs. Unicode)

اینجا یه نکته کلیدی وجود داره که باید برای همیشه بهش مسلط بشی:

[0-9] (کلاس کاراکتر صریح): این دستور یه عبارت کاملاً دقیق و “تحت‌اللفظی” (Literal) هست. وقتی می‌نویسی [0-9]، تو دقیقاً به موتور رجکس می‌گی: «فقط و فقط دنبال یکی از این ده تا کاراکتر ASCII (استاندارد پایه انگلیسی) بگرد: , 1, 2, 3, 4, 5, 6, 7, 8, 9». این دستور هیچ‌وقت اعداد فارسی (۱۲۳) یا عربی (١٢٣) رو تطبیق نمی‌ده.

d (میان‌بُر کلاس کاراکتر): این دستور یه «میان‌بر» هوشمنده. در موتورهای رجکس قدیمی، d دقیقاً معادل [0-9] بود. اما در موتورهای مدرن (مثل پایتون، جاوااسکریپت جدید، .NET، PHP با فلگ u)، d آگاه به یونیکد (Unicode-aware) شده. این یعنی چی؟ یعنی d به معنی «هر کاراکتری که در استاندارد یونیکد به عنوان رقم (Digit) شناخته می‌شه» هست. و این استاندارد شامل ده‌ها نوع عدد مختلف از زبان‌های مختلف دنیاست!

آیا d اعداد فارسی (مانند ۱، ۲، ۳) را تطبیق می‌دهد؟ (پاسخ: بستگی به موتور دارد)

جواب کوتاه و مستقیم: بله، در اکثر موتورهای مدرن، dاعداد فارسی را هم تطبیق می‌دهد.

اعداد فارسی که ما استفاده می‌کنیم (۰۱۲۳۴۵۶۷۸۹) در استاندارد یونیکد به عنوان «ارقام عربی-هندی» (Arabic-Indic Digits) شناخته می‌شن. اعداد عربی رایج (٠١٢٣٤٥٦٧٨٩) هم «ارقام عربی-هندی شرقی» (Eastern Arabic-Indic Digits) هستن.

در موتورهای مدرن:

در پایتون (Python 3): بله، d به صورت پیش‌فرض اعداد فارسی رو هم می‌شناسه.

در جاوااسکریپت (JavaScript): بله، اگه از فلگ u (برای Unicode) استفاده کنی (مثلاً /d/u)، اعداد فارسی رو هم تطبیق می‌ده.

در PHP (PCRE): بله، اگه از مُدیفایر u (برای UTF-8) استفاده کنی (مثلاً /d/u)، اعداد فارسی رو می‌شناسه.

این رفتار “هوشمندانه” می‌تونه هم خوب باشه هم بد. خوبه چون اگه کاربر توی فرم شماره موبایلش رو با اعداد فارسی (۰۹۱۲…) هم وارد کرد، سیستم تو می‌فهمتش. اما اگه جایی فقط اعداد انگلیسی می‌خوای، فاجعه می‌شه.

چگونه تطبیق فقط اعداد انگلیسی (ASCII) را تضمین کنیم؟

حالا می‌رسیم به سناریوی حیاتی. فرض کن داری شماره کارت بانکی (که همیشه باید با اعداد انگلیسی 123 باشه) یا یه شناسه API رو اعتبارسنجی می‌کنی. تو نباید اجازه بدی کاربر اعداد فارسی (۱۲۳) وارد کنه.

اگه از d استفاده کنی، ممکنه ورودی اشتباهی رو قبول کنی.

راه حل تضمینی و قطعی: هر وقت خواستی مطمئن بشی که فقط و فقط اعداد انگلیسی (ASCII) تطبیق داده می‌شن، هرگز از dاستفاده نکن.

به‌جای اون، مستقیم از همون کلاس کاراکتر صریح استفاده کن: [0-9]

این دستور در همه‌ی موتورها، با همه‌ی تنظیمات و همه‌ی فلگ‌ها، فقط و فقط ده کاراکتر تا 9 رو می‌شناسه و خیال تو رو راحت می‌کنه.

مثال اعتبارسنجی شماره کارت (۱۶ رقمی):

الگوی اشتباه (وابسته به موتور): ^d{16}$ (این ممکنه ۱۶ رقم فارسی رو هم قبول کنه!)

الگوی صحیح (تضمین‌شده فقط انگلیسی): ^[0-9]{16}$ (این الگو فقط 16 رقم انگلیسی رو از اول تا آخر رشته قبول می‌کنه.)

پیاده‌سازی d و D در زبان‌های برنامه‌نویسی

خوشبختانه، d و D جزو پایه‌ای‌ترین دستورات رجکس هستن و تقریباً توی همه‌ی زبان‌های برنامه‌نویسی مدرن که از عبارات باقاعده پشتیبانی می‌کنن، به یه شکل کار می‌کنن. بیا دوتا از محبوب‌ترین‌ها، یعنی پایتون و جاوا اسکریپت، رو با هم ببینیم.

مثال در پایتون (ماژول re)

توی پایتون، ما برای کار با رجکس از ماژول داخلی re استفاده می‌کنیم. یادت باشه که d در پایتون ۳ به‌صورت پیش‌فرض یونیکد (از جمله اعداد فارسی) رو هم می‌شناسه.

۱. استخراج اعداد (Data Extraction): فرض کن می‌خوای همه‌ی اعداد رو از یه متن بکشی بیرون.

import re

text = “قیمت 1500 تومان است و 20 عدد موجودی داریم. (کد: ۱۲۳)”

# d+ یعنی یک یا چند رقم پشت سر هم

# re.findall() همه‌ی نتایج رو به صورت یه لیست برمی‌گردونه

numbers = re.findall(r’d+’, text)

print(numbers)

# خروجی: [‘1500′, ’20’, ‘۱۲۳’]

# توجه کن که ‘۱۲۳’ فارسی رو هم پیدا کرد!

۲. پاکسازی شماره تلفن (Data Cleaning): حالا می‌خوایم یه شماره تلفن رو پاکسازی کنیم و فقط اعداد رو نگه داریم.

import re

phone_raw = “+98 (912) 123-4567”

# D+ یعنی یک یا چند کاراکتر غیر عددی

# re.sub(pattern, replace, string)

# ما بهش می‌گیم هر D+ رو با هیچی (“”) جایگزین کن

phone_clean = re.sub(r’D+’, ”, phone_raw)

print(phone_clean)

# خروجی: ‘989121234567’

مثال در جاوا اسکریپت (JavaScript Regex)

توی جاوا اسکریپت، رجکس بخشی از خود زبانه و کار باهاش خیلی راحته. ما الگوها رو بین دوتا اسلش / می‌نویسیم.

۱. استخراج اعداد (Data Extraction): مثل مثال پایتون، می‌خوایم همه‌ی اعداد رو پیدا کنیم.

let text = “قیمت 1500 تومان است و 20 عدد موجودی داریم. (کد: ۱۲۳)”;

// /pattern/flags

// d+ یعنی یک یا چند رقم

// g یعنی global (سرتاسری)، تا بعد از اولین پیدا کردن متوقف نشه

// u یعنی unicode، تا اعداد فارسی رو هم بشناسه

let pattern = /d+/gu;

let numbers = text.match(pattern);

console.log(numbers);

// خروجی: [“1500”, “20”, “۱۲۳”]

۲. پاکسازی شماره تلفن (Data Cleaning): اینجا هم از متد replace() برای پاکسازی استفاده می‌کنیم.

let phoneRaw = “+98 (912) 123-4567”;

// D یعنی هر کاراکتر غیر عددی

// g یعنی global، تا همه‌ی D ها رو جایگزین کنه (نه فقط اولی رو)

let pattern = /D/g;

// هرچیزی که D هست رو با هیچی (“”) جایگزین کن

let phoneClean = phoneRaw.replace(pattern, “”);

console.log(phoneClean);

// خروجی: “989121234567”

تست در ابزارهای آنلاین (مانند Regex101)

قبل از اینکه الگوی رجکست رو مستقیم توی کدت استفاده کنی، یه قانون طلایی وجود داره: همیشه اول تستش کن!

ابزارهایی مثل Regex101.com برای همین ساخته شدن. این سایت‌ها به تو اجازه می‌دن:

متن آزمایشی (Test String): متنی که می‌خوای روش جستجو کنی رو وارد می‌کنی.

الگوی رجکس (Regular Expression): الگوت رو می‌نویسی (مثلاً d+).

توضیحات (Explanation): سایت قدم به قدم بهت توضیح می‌ده که الگوت دقیقاً داره چی کار می‌کنه.

نتایج (Match Information): به‌صورت زنده بهت نشون می‌ده که کجاهای متن با الگوت تطبیق پیدا کرده.

چرا این مهمه؟

صرفه‌جویی در وقت: به جای اینکه ۱۰ بار کدت رو اجرا کنی تا باگش رو پیدا کنی، در لحظه الگوت رو اصلاح می‌کنی.

تست سناریوهای مرزی: می‌تونی همونجا تست کنی که آیا الگوت اعداد فارسی رو می‌گیره یا نه؟ آیا [0-9] درست کار می‌کنه؟ آیا ^ و $ رو درست گذاشتی؟

پیشنهاد من: همین الان برو توی Regex101 و این دوتا الگو رو روی متن Hello 123 – ۱۲۳ تست کن تا تفاوتشون رو با چشم ببینی:

d+ (با فلگ u یا حالت پایتون/جاوااسکریپت)

[0-9]+

جدول مقایسه سریع: d در برابر D

برای اینکه همه‌چی توی ذهنت دسته‌بندی بشه، این جدول خلاصه‌ی همه‌چیزه:

ویژگی (Feature) d (Digit) D (Non-Digit)
معنی «هر رقم عددی» «هر کاراکتر غیر عددی»
معادل کلاسیک (ASCII) [0-9] [^0-9]
رفتار یونیکد (مدرن) شامل اعداد فارسی، عربی و… (۱۲۳) هرچیزی که رقم یونیکد نیست
مثال‌های تطبیق ‘7’، ‘0’، ‘۳’ (در حالت یونیکد) ‘A’، ‘z’، .، ‘!’، ‘-‘، ‘ ‘ (فاصله)
مثال‌های عدم تطبیق ‘a’، ‘+’، ‘ ‘ (فاصله) ‘9’، ‘1’، ‘۵’ (در حالت یونیکد)
کاربرد اصلی استخراج اعداد، اعتبارسنجی فرم (سن، کدپستی) پاکسازی داده (حذف حروف و نمادها از شماره تلفن)

جمع‌بندی

خب، اینم از سفر کامل ما به دنیای d و D! حالا تو دقیقاً می‌دونی این دو میان‌بر قدرتمند در رجکس چی هستن و چطور باید ازشون هوشمندانه استفاده کنی.

یاد گرفتی که d چطور برای استخراج اعداد و اعتبارسنجی فرم‌ها (مثل کد پستی یا سن) به کارت میاد و در مقابل، D چطور مثل یه جاروبرقی، داده‌هات رو از شر کاراکترهای اضافه پاکسازی می‌کنه (مثل تمیز کردن شماره تلفن).

از همه مهم‌تر، الان تفاوت حیاتی بین d (که می‌تونه یونیکد و اعداد فارسی رو هم بشناسه) و [0-9] (که فقط اعداد انگلیسی رو می‌شناسه) درک می‌کنی. این همون نکته‌ی تخصصیه که جلوی خیلی از باگ‌های سیستمت رو می‌گیره. حالا می‌تونی با خیال راحت‌تری کدهای تمیزتر و دقیق‌تری بنویسی.

سوالات متداول (FAQ)

در ادامه چندتا سوال پرتکرار رو جواب می‌دم که ممکنه برات پیش اومده باشه:

۱. تفاوت اصلی d و D چیست؟

خیلی ساده‌ست: d (digit) دنبال یک رقم عددی می‌گرده. D (non-digit) دقیقاً برعکسه و دنبال هر کاراکتری که عدد نیست (مثل حروف، نمادها یا فاصله) می‌گرده.

۲. چطور فقط اعداد انگلیسی (0 تا 9) را پیدا کنم و نه اعداد فارسی (۰ تا ۹)؟

عالی! این نکته خیلی مهمه. هرگز از d استفاده نکن، چون ممکنه اعداد فارسی رو هم بشناسه. به جاش، همیشه از کلاس کاراکتر صریح [0-9] استفاده کن تا تضمین کنی فقط اعداد انگلیسی (ASCII) تطبیق داده می‌شن.

۳. چطور یک عدد با طول مشخص (مثلاً دقیقاً ۵ رقمی) را پیدا کنم؟

تو باید از “تکرارکننده‌ها” (Quantifiers) استفاده کنی. مثلاً d{5} یعنی دقیقاً ۵ رقم پشت سر هم. اگه می‌خوای مطمئن بشی کل رشته فقط همین ۵ رقمه و نه بیشتر، از ^d{5}$ استفاده کن.

۴. چطور تمام حروف و نمادها را از یک رشته حذف کنم و فقط اعداد بمانند؟

این کاربرد کلاسیک D هست. تو باید از قابلیت “جایگزینی” (Replace) استفاده کنی. الگوی D+ رو جستجو کن و اون رو با یک رشته‌ی خالی (“”) جایگزین کن. این کار هرچیزی که عدد نیست رو حذف می‌کنه.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *