فرصت مطالعه ندارید؟ چکیده این مطلب را همینجا گوش دهید:
کار با دادههای متنی زبان فارسی در فرمها و وبسایتها همیشه یکی از چالشبرانگیزترین بخشهای توسعه نرمافزار بوده است. از تفاوت بین ارقام فارسی و انگلیسی گرفته تا حضور کاراکترهای مخفی مانند نیمفاصله (Zero-Width Non-Joiner) یا همان (ZWNJ)، برنامهنویسان را ناچار میکند تا به سراغ ابزارهای قدرتمندی مثل عبارات باقاعده یا همان ریجکس (Regex) بروند. نوشتن یک الگوی استاندارد که بتواند خطاهای کاربری را به حداقل برساند و دادههای تمیز تحویل پایگاه داده بدهد، مهارتی کلیدی است که در این مقاله ۵ الگوی حیاتی آن را بررسی میکنیم.
اگر در پروژههای وب خود با مسائل مشابه سروکار دارید، پیشنهاد میکنیم نگاهی هم به مقاله کاربردی رمزگشایی خطاهای رایج URL Encoding و راهنمای مدیریت لینکهای فارسی بیندازید تا درک بهتری از نحوه مدیریت کاراکترهای خاص در بستر وب پیدا کنید. در ادامه، الگوهای آماده و تستشدهای را مرور میکنیم که میتوانید مستقیماً در کدهای پایتون یا جاوااسکریپت خود کپی کنید.
جدول خلاصهی الگوهای ریجکس فارسی
| نوع داده | هدف اعتبارسنجی | پشتیبانی از ارقام فارسی/عربی | توضیح کلیدی |
|---|---|---|---|
| شماره موبایل | تایید شمارههای همراه ایران | بله (تبدیل خودکار) | شناسایی پیششمارههای معتبر (۰۹…) |
| کد ملی | بررسی ساختار ۱۰ رقمی | بله | فقط ساختار ارقام؛ کنترل رقم کنترلی نیاز به منطق کمکی دارد |
| نیمفاصله | یافتن یا جایگزینی فاصله مجازی | ندارد (مختص کاراکتر) | شناسایی با یونیکد \u200c |
| پلاک خودرو | تطبیق فرمت استاندارد ملی | بله | پشتیبانی از حروف خاص مثل «الف»، «ب»، «پ» |
| کلمه و متن خالص فارسی | جلوگیری از ورود کاراکترهای نامعتبر | بله | پوشش کامل حروف الفبای فارسی و اعراب |
۱. الگوی ریجکس شماره تلفن همراه ایران
شمارههای موبایل در ایران با پیششماره ۰۹ شروع میشوند و ۹ رقم بعد از آن میآیند. چالش اصلی کاربران، استفاده از فاصلهها، خط تیره یا وارد کردن ارقام به صورت فارسی است. الگوی زیر تمامی این حالات را پوشش میدهد.
import re
# الگوی ریجکس برای شماره موبایل ایران (با پشتیبانی از ارقام فارسی و فاصلههای احتمالی)
mobile_pattern = re.compile(r'^(?:0|98|\+98)?([۰-۹0-9]{10})$')
def validate_mobile(phone_number):
# پاکسازی کاراکترهای اضافی مثل فاصله یا خط تیره
cleaned = re.sub(r'[\s\-\(\)]', '', phone_number)
# تبدیل ارقام فارسی به انگلیسی برای پردازش دقیقتر
persian_to_english = str.maketrans('۰۱۲۳۴۵۶۷۸۹', '0123456789')
normalized = cleaned.translate(persian_to_english)
match = mobile_pattern.match(normalized)
if match:
# بررسی اینکه آیا بعد از کد کشور یا صفر، پیششماره با 9 شروع میشود
digits = match.group(1)
if digits.startswith('9'):
return True
return False
# نمونه استفاده
print(validate_mobile("09123456789")) # خروجی: True
print(validate_mobile("۰۹۱۲ ۳۴۵ ۶۷۸۹")) # خروجی: True
print(validate_mobile("08123456789")) # خروجی: False
در این قطعه کد، تابع ابتدا کاراکترهای فاصلهدار و خط تیره را حذف میکند. سپس با استفاده از جدول تبدیل یونیکد، اعداد فارسی را به انگلیسی برمیگرداند تا تطبیق با الگوی \d یا بازه مشخص شده به درستی انجام شود.
۲. الگوی ریجکس ساختار کد ملی ۱۰ رقمی
کد ملی ایران یک رشته دقیقاً ۱۰ رقمی است. اگرچه اعتبارسنجی نهایی کد ملی نیاز به یک الگوریتم ریاضی (چکدیجیت) دارد، اما ریجکس اولین خط دفاعی برای جلوگیری از ورود کاراکترهای غیرمجاز یا طول نادرست است.
// تابع اعتبارسنجی ساختار کد ملی در جاوااسکریپت
function isValidNationalCodeStructure(code) {
// تبدیل ارقام فارسی به انگلیسی در صورت وجود
const englishCode = code.replace(/[۰-۹]/g, function(w) {
return '۰۱۲۳۴۵۶۷۸۹'.indexOf(w);
}).trim();
// الگوی دقیقاً ۱۰ رقم متوالی
const nationalCodeRegex = /^[0-9]{10}$/;
if (!nationalCodeRegex.test(englishCode)) {
return false;
}
// جلوگیری از وارد کردن ۱۰ رقم یکسان مثل 0000000000
if (/^(\d)\1{9}$/.test(englishCode)) {
return false;
}
return true;
}
// نمونه تست
console.log(isValidNationalCodeStructure("0031234567")); // خروجی: true
console.log(isValidNationalCodeStructure("۱۲۳۴۵۶۷۸۹۰")); // خروجی: true
console.log(isValidNationalCodeStructure("12345")); // خروجی: false
این کد نه تنها طول ۱۰ رقمی را بررسی میکند، بلکه با استفاده از شرط زنجیرهای ^(\d)\1{9}$ از ورود کدهای نامعتبری که تمام ارقام آنها یکسان است (مثل ده تا صفر) نیز جلوگیری مینماید.
۳. مدیریت نیمفاصله (Zero-Width Non-Joiner) در متنهای فارسی
بسیاری از کاربران به جای استفاده از کاراکتر استاندارد نیمفاصله (\u200c)، از فاصله معمولی استفاده میکنند که ظاهر متن را خراب میکند. برای پیداکردن یا اصلاح این مورد در پردازش متن، از ریجکس زیر بهره میبریم.
import re
def fix_half_spaces(text):
# شناسایی فاصلههای اشتباه قبل یا بعد از پسوندها و پیشوندها مثل «میشود» یا «دانشگاهها»
# کاراکتر \u200c همان نیمفاصله استاندارد است
pattern = r'\b(می|نمی|بی)\s+([م-ی])'
# اصلاح فاصله معمولی به نیمفاصله استاندارد
fixed_text = re.sub(pattern, r'\1\2', text)
return fixed_text
# نمونه استفاده
sample_text = "او می خواهد کتاب را بخواند."
print(fix_half_spaces(sample_text))
# خروجی: او میخواهد کتاب را بخواند. (با نیمفاصله استاندارد)
نکته مهم در اینجا استفاده از کاراکتر یونیکد \u200c است. هنگام نوشتن اسکریپتهای پایتون یا جاوااسکریپت، اطمینان حاصل کنید که فایل سورس کد شما با انکودینگ UTF-8 ذخیره شده باشد تا کاراکترهای فارسی و نیمفاصله به درستی خوانده شوند.
۴. الگوی ریجکس پلاک خودروهای ملی ایران
فرمت پلاکهای جدید خودرو در ایران شامل دو رقم، یک حرف فارسی، سه رقم و دو رقم منطقه است (مثل: ۱۲ ب ۳۴۵ – ۶۷). ساخت این ریجکس نیازمند شناخت دقیق حروف مجاز در پلاکهای ایران است.
// الگوی پلاک خودروی ملی (سادهسازی شده برای فرمهای ثبتنام)
function validateCarPlate(plateStr) {
// حروف رایج در پلاک ملی (الف، ب، پ، ت، ج، د، ر، ز، س، ش، ص، ط، ع، ف، ق، ک، گ، ل، م، ن، و، ه، ی)
const persianLetters = '[الف-ی]';
// ساختار: دو رقم + یک حرف + سه رقم + ایران + دو رقم منطقه
// مثال: 12 ب 345 إيران 67
const plateRegex = new RegExp(`^([0-9۰-۹]{2})\\s*(${persianLetters})\\s*([0-9۰-۹]{3})\\s*ایران\\s*([0-9۰-۹]{2})$`);
return plateRegex.test(plateStr.trim());
}
// نمونه استفاده
console.log(validateCarPlate("12 ب 345 ایران 11")); // خروجی: true
console.log(validateCarPlate("۱۲ج۴۵۶ایران۲۲")); // خروجی: true
این الگو به کاربران اجازه میدهد پلاک خودرو را با فاصلههای دلخواه یا حتی بدون فاصله وارد کنند، در حالی که ساختار کلی آن توسط سیستم اعتبارسنجی تایید میشود.
۵. پاکسازی و فیلتر کاراکترهای نامعتبر در ورودیهای متنی
گاهی اوقات کاربران کدهای مخرب یا کاراکترهای کنترلی عجیب را در فرمهای ثبتنام کپی میکنند. الگوی زیر به شما کمک میکند تمام کاراکترهایی که حروف فارسی، ارقام و علائم نگارشی استاندارد نیستند را حذف کنید.
import re
def sanitize_persian_text(user_input):
# اجازه دادن فقط به حروف فارسی، اعداد فارسی/انگلیسی، فاصله، نیمفاصله و علائم نگارشی متداول
# استفاده از بازه یونیکد حروف فارسی (\u0600-\u06FF)
pattern = r'[^0-9۰-۹a-zA-Z\u0600-\u06FF\s\u200c\.\,\?\!\،\؛]'
cleaned_text = re.sub(pattern, '', user_input)
return cleaned_text
# نمونه استفاده
malicious_input = "سلام! لطفاً بررسی کنید."
print(sanitize_persian_text(malicious_input))
# خروجی: سلام! alert('hack') لطفاً بررسی کنید. (تگهای اسکریپت و کاراکترهای غیرمجاز حذف شدند)
اگرچه این روش جایگزین ابزارهای ایمنی سمت سرور مثل Escape کردن خروجیها نمیشود، اما به عنوان لایه اول فیلتر در فرانتاند بسیار کارآمد است.
پرسشهای متداول
چرا در نوشتن ریجکس برای زبان فارسی با خطای کاراکترهای ناشناخته مواجه میشویم؟
دلیل اصلی، عدم تنظیم انکودینگ فایل سورس روی UTF-8 یا استفاده از ابزارهای قدیمی است که استانداردهای یونیکد را به درستی پشتیبانی نمیکنند. همیشه مطمئن شوید محیط توسعه شما روی UTF-8 تنظیم شده است.
آیا ارقام فارسی و انگلیسی در ریجکس به طور خودکار یکسان شناخته میشوند؟
خیر. در ریجکس استاندارد، کاراکتر \d تنها اعداد انگلیسی (0 تا 9) را پوشش میدهد. برای ارقام فارسی باید صراحتاً بازه یونیکد آنها را وارد کنید یا پیش از بررسی، ارقام را به انگلیسی تبدیل نمایید.
چگونه پرفورمنس اجرای ریجکس را در متنهای بسیار طولانی بالا ببریم؟
برای متنهای حجیم، حتماً از متد کامپایل کردن الگو (مثل re.compile در پایتون) استفاده کنید تا الگو بارها پردازش نشود. همچنین از ایجاد گروههای اسیرکننده غیرضروری (Capturing Groups) پرهیز کنید.
جمعبندی
تسلط بر عبارات باقاعده (Regex) برای مدیریت دادههای فارسی، ابزاری قدرتمند در جعبهابزار هر برنامهنویس وب است. با استفاده از الگوهای ارائه شده در این مقاله برای شماره موبایل، کد ملی، نیمفاصله و پاکسازی متن، میتوانید تجربه کاربری بهتری خلق کنید و از ورود دادههای مخدوش به سیستم جلوگیری نمایید. پیادهسازی این الگوها در لایه فرانتاند و تکرار مجدد آنها در سمت سرور، بالاترین سطح امنیت و پایداری را برای نرمافزار شما به ارمغان میآورد.




