PHP / Тогтмол илэрхийлэл (RegExp)
Тогтмол илэрхийлэл (RegExp)
Regular expression буюу товчоор regex нь мөр дотроос хэв загвар хайх, таарах эсэхийг шалгах, солих боломж олгодог хүчирхэг хэрэгсэл юм. Имэйл, утасны дугаар, нууц үг шалгах; лог файл задлах; HTML-с мэдээлэл гаргах зэрэг газарт regex зайлшгүй хэрэгтэй болдог. Эхлэхэд арай хэцүү мэт санагдаж болох ч жишээнүүдтэй хамт сурвал маш хурдан ойлгогдоно.
Regex үндсэн бүтэц ба тэмдэгтүүд
PHP-д regex нь /хэв загвар/тугнууд хэлбэртэй байна:
php
<?php
// preg_match() — таарах эсэхийг шалгана
// 1 буцаана (таарсан), 0 буцаана (тааралтгүй), false (алдаа)
// . — ямар ч нэг тэмдэгт
preg_match('/h.t/', 'hat'); // 1 — h + дурын тэмдэгт + t
preg_match('/h.t/', 'heat'); // 0 — хоёр тэмдэгт таарсангүй
// ^ — мөрийн эхлэл, $ — мөрийн төгсгөл
preg_match('/^PHP/', 'PHP бол хэл'); // 1 — PHP-р эхэлнэ
preg_match('/хэл$/', 'PHP бол хэл'); // 1 — хэл-ээр дуусна
preg_match('/^PHP$/', 'PHP бол хэл'); // 0 — яг PHP биш
// \d — тоо [0-9], \w — үсэг/тоо/доогуур зураас, \s — хоосон зай
preg_match('/\d{4}/', '2024-01-15'); // 1 — 4 тоо
preg_match('/\w+/', 'Сайн_уу'); // 1 — нэг ба түүнээс олон \w
preg_match('/\s/', 'PHP хэл'); // 1 — хоосон зай байна
// Тоолуур: * (0+), + (1+), ? (0 эсвэл 1), {n}, {n,m}
preg_match('/go+gle/', 'google'); // 1
preg_match('/colou?r/', 'color'); // 1 — u нь заавал биш
preg_match('/\d{3}-\d{4}/', '976-1234'); // 1
?>
Тэмдэгтийн анги ба өөр хувилбарууд
php
<?php
// [] — тэмдэгтийн анги
preg_match('/[aeiou]/', 'PHP'); // 0 — эгшиг байхгүй
preg_match('/[aeiou]/', 'email'); // 1 — e эгшиг байна
// [^] — сөрөг анги (байх ёсгүй тэмдэгтүүд)
preg_match('/[^0-9]/', '12345'); // 0 — зөвхөн тоо
preg_match('/[^0-9]/', '123a5'); // 1 — тоо биш тэмдэгт байна
// | — эсвэл (OR)
preg_match('/cat|dog|bird/', 'I have a dog'); // 1
preg_match('/^(PHP|Python|Go)$/', 'PHP'); // 1
// () — бүлэг — барих ба нэгтгэх
preg_match('/(\d{4})-(\d{2})-(\d{2})/', '2024-01-15', $тохирол);
echo $тохирол[0]; // 2024-01-15 (бүтэн тохирол)
echo $тохирол[1]; // 2024 (1-р бүлэг)
echo $тохирол[2]; // 01 (2-р бүлэг)
echo $тохирол[3]; // 15 (3-р бүлэг)
// Тугнууд: i (том/жижиг үл харгалзах), m (олон мөр), s (. нь \n-г ч барина)
preg_match('/php/i', 'I love PHP'); // 1 — том/жижиг үл харгалзана
?>
preg_match_all — бүх тохирлыг олох
php
<?php
$текст = "Холбоо барих: 99001122, 88223344, 77445566 дугаарт залгана уу.";
// Бүх тохирлыг олно
$тоо = preg_match_all('/\d{8}/', $текст, $дугаарууд);
echo "Олдсон тоо: $тоо\n"; // 3
print_r($дугаарууд[0]); // ['99001122', '88223344', '77445566']
// Нэрлэсэн бүлэг (?P<нэр>...)
$огноо = "Захиалга: 2024-06-15, хүргэлт: 2024-06-20";
preg_match_all(
'/(?P<жил>\d{4})-(?P<сар>\d{2})-(?P<өдөр>\d{2})/',
$огноо,
$огноонууд,
PREG_SET_ORDER
);
foreach ($огноонууд as $о) {
echo "{$о['жил']} оны {$о['сар']} сарын {$о['өдөр']}\n";
}
// 2024 оны 06 сарын 15
// 2024 оны 06 сарын 20
?>
preg_replace — хэв загвараар солих
php
<?php
// Энгийн солих
$текст = "Утас: 9900-1122, нөөц: 8833-4455";
$цэвэр = preg_replace('/\d{4}-\d{4}/', '****-****', $текст);
echo $цэвэр; // Утас: ****-****, нөөц: ****-****
// Барьсан бүлгийг ашиглах ($1, $2 ...)
$огноо = "15/06/2024";
$шинэ = preg_replace('/(\d{2})\/(\d{2})\/(\d{4})/', '$3-$2-$1', $огноо);
echo $шинэ; // 2024-06-15
// Олон хэв загвар нэгэн зэрэг солих
$хуур = ["/<[^>]+>/", "/\s+/", "/^\s+|\s+$/"];
$орлуулагч = ["", " ", ""];
$цэвэр_текст = preg_replace($хуур, $орлуулагч, "<p> Сайн уу </p>");
echo $цэвэр_текст; // Сайн уу
// Callback функцтай preg_replace_callback
$мөр = "Үнэ: 25000 төгрөг, 79000 төгрөг";
$форматтай = preg_replace_callback('/\d+/', function ($тохирол) {
return number_format((int) $тохирол[0]);
}, $мөр);
echo $форматтай; // Үнэ: 25,000 төгрөг, 79,000 төгрөг
?>
Практик жишээ — оролт баталгаажуулах
Regex-ийн хамгийн нийтлэг хэрэглээ бол маягтын оролт шалгах:
php
<?php
class Validator
{
// Имэйл шалгах
public static function имэйл(string $утга): bool
{
return (bool) preg_match(
'/^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/',
$утга
);
}
// Монгол утасны дугаар: 8 оронтой, 6, 7, 8, 9-р эхэлнэ
public static function утас(string $утга): bool
{
return (bool) preg_match('/^[6-9]\d{7}$/', $утга);
}
// Нууц үг: 8+ тэмдэгт, нэг том үсэг, нэг тоо
public static function нууц_үг(string $утга): bool
{
return strlen($утга) >= 8
&& preg_match('/[A-Z]/', $утга)
&& preg_match('/[0-9]/', $утга);
}
// Огноо: YYYY-MM-DD
public static function огноо(string $утга): bool
{
if (!preg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $утга, $х)) {
return false;
}
return checkdate((int)$х[2], (int)$х[3], (int)$х[1]);
}
}
// Ашиглах
var_dump(Validator::имэйл("user@example.mn")); // bool(true)
var_dump(Validator::имэйл("буруу@")); // bool(false)
var_dump(Validator::утас("99001122")); // bool(true)
var_dump(Validator::утас("12345678")); // bool(false) — 1-р эхэлсэн
var_dump(Validator::нууц_үг("Mypass1!")); // bool(true)
var_dump(Validator::огноо("2024-02-30")); // bool(false) — 30 байхгүй
?>
Дараагийн хичээлд:
Огноо ба цагтай ажиллахыг судална. date(), strtotime(), DateTime класс болон цагийн бүс (timezone) зохицуулахыг — Улаанбаатарын цагийн бүсэд онцгой анхаарлаа хандуулан — үзнэ.