Hi, my name is Vitalii Rudnykh πŸ‘‹

May 27, 2022

πŸ“” Best practices для рСгулярок Π² PHP

Π‘ΠΎΠ±Ρ€Π°Π» здСсь Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ best practices, Π»Π°ΠΉΡ„Ρ…Π°ΠΊΠΈ ΠΈ Ρ€Π°Π·Π½Ρ‹Π΅ Π·Π°ΠΌΠ΅Ρ‚ΠΊΠΈ ΠΏΡ€ΠΎ использованиС рСгулярных Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ Π½Π° PHP.

lion

НС ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ рСгулярныС выраТСния, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ. βœ‹

РСгулярки это слоТно. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ, ΠΈΠ·Π±Π΅Π³Π°ΠΉ ΠΈΡ… использования Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ. НиТС нСсколько ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠ², ΠΊΠΎΠ³Π΄Π° рСгулярныС выраТСния слСдуСт ΠΈΠ·Π±Π΅Π³Π°Ρ‚ΡŒ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Π½Ρ‹Π΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ:

Π—Π°Π΄Π°Ρ‡Π°Π Π΅ΡˆΠ΅Π½ΠΈΠ΅
ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° адрСса элСктронной ΠΏΠΎΡ‡Ρ‚Ρ‹Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ filter_var() с FILTER_VALIDATE_EMAIL *
ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° IP Π°Π΄Ρ€Π΅ΡΠ°Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ filter_var() с FILTER_VALIDATE_IP
ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° URLΠ˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ filter_var() с FILTER_VALIDATE_URL *
ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π΄Π°Ρ‚Ρ‹Π‘ΠΌ. эту Ρ‚Π΅ΠΌΡƒ Π½Π° Stack Overflow.
ΠŸΠ°Ρ€ΡΠΈΠ½Π³ JSONΠ˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ json_decode().
ΠŸΠ°Ρ€ΡΠΈΠ½Π³ HTML/XMLΠ˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΉ парсСр. Π‘ΠΌ. Ρ‚Π΅ΠΌΡƒ Π½Π° Stack Overflow: How do you parse and process HTML/XML in PHP?
ΠŸΠ°Ρ€ΡΠΈΠ½Π³ CSVΠ˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ str_getcsv() ΠΈΠ»ΠΈ fgetcsv().
ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° наличия Π² строкС ΠΏΠΎΠ΄ΡΡ‚Ρ€ΠΎΠΊΠΈΠ˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ strpos() ΠΈΠ»ΠΈ stripos().
ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π° Ρ‡ΠΈΡΠ»Π°Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ сравнСния.

* ΠΌΠΎΠΆΠ΅Ρ‚ Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с Π½Π°Ρ†ΠΈΠΎΠ½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΌΠΈ Π΄ΠΎΠΌΠ΅Π½Π½Ρ‹ΠΌΠΈ ΠΈΠΌΠ΅Π½Π°ΠΌΠΈ ΠΈ адрСсами элСктронной ΠΏΠΎΡ‡Ρ‚Ρ‹

Π—Π½Π°ΠΉ доступныС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ рСгулярных Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ. 🧠

Помимо классичСских preg_match() ΠΈ preg_replace() Π΅ΡΡ‚ΡŒ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΎ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΌΠ½ΠΎΠ³ΠΈΠ΅ Π½Π΅ Π·Π½Π°ΡŽΡ‚.

preg_split()

Иногда трСбуСтся Ρ€Π°Π·Π±ΠΈΡ‚ΡŒ тСкст ΠΏΠΎ Ρ€Π°Π·Π΄Π΅Π»ΠΈΡ‚Π΅Π»ΡŽ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ рСгулярку, вмСсто ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π°:

$input = 'preg__split_for___fun';
if(preg_match_all('/[^_]+/', $input, $m)) {
    print_r($m[0]);
} else {
    echo 'no match';
}

ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΠΉ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ Ρ‚Π°ΠΊ:

$input = 'preg__split_for___fun';
$output = preg_split('/_+/', $input);
print_r($output);

preg_grep()

Если Π²Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΠΏΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ массив ΠΈ ΡΠΎΠΏΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ значСния с ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΌ рСгулярным Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ΠΌ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ preg_grep().

$input = ['data1', 'data2', 'exclude', 'data3'];
$result = [];
foreach ($input as $v) {
    if(preg_match('/data\d+/', $v)) {
        $result[] = $v;
    }
}
print_r($result); // Array ( [0] => data1 [1] => data2 [2] => data3 )

Π’Π°ΠΊΠΎΠΉ ΠΆΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

$input = ['data1', 'data2', 'exclude', 'data3'];
$result = preg_grep('/data\d+/', $input);
print_r($result); // Array ( [0] => data1 [1] => data2 [3] => data3 )

ЕдинствСнноС Ρ‡Ρ‚ΠΎ Π½ΡƒΠΆΠ½ΠΎ ΡƒΡ‡Π΅ΡΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ preg_grep() Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ массив проиндСксированный ΠΏΠΎ ΠΊΠ»ΡŽΡ‡Π°ΠΌ ΠΈΠ· Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ массива.

preg_filter()

Богласно Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ:

preg_filter() is identical to preg_replace() except it only returns the (possibly transformed) subjects where there was a match.

По сути, это Ρ‚ΠΎ ΠΆΠ΅ самоС, Ρ‡Ρ‚ΠΎ ΠΈ preg_grep(), Π½ΠΎ с ΠΎΠΏΡ†ΠΈΠ΅ΠΉ replace.

preg_replace_callback()

Ѐункция Π·Π°ΠΌΠ΅Π½Ρ‹ с Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒΡŽ использования ΠΊΠΎΠ»Π»-Π±Π΅ΠΊ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. НапримСр, Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ Π²Ρ‹Π±Ρ€Π°Ρ‚ΡŒ нСсколько слов ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡ… Π² Π²Π΅Ρ€Ρ…Π½ΠΈΠΉ рСгистр:

$input = 'words are important';
$output = preg_replace_callback('/\w+/', function($m) {
    return strtoupper($m[0]);
}, $input);
echo $output;

preg_quote()

Ѐункция экранирования символов Π² рСгулярных выраТСниях. ΠœΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΈΠ³ΠΎΠ΄ΠΈΡ‚ΡŒΡΡ Π² случаС Ссли трСбуСтся ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ Π²Π²ΠΎΠ΄ Π² рСгулярку:

$user_input = isset($_GET['input']) ? (string) $_GET['input'] : '';
$haystack = 'List: pid1000, pid2000, pid3000...';
$regex = '/' . preg_quote($user_input, '/') . '\d+/';
if(preg_match_all($regex, $haystack, $m)) {
    print_r($m[0]);
} else {
    echo 'no match';
}

preg_last_error()

Π­Ρ‚Π° функция ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΈΠ³ΠΎΠ΄ΠΈΡ‚ΡŒΡΡ для ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ, ΠΎΠ½Π° Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΊΠΎΠ΄ ошибки послСднСго выполнСния PCRE Regex. Ѐункция для прСобразования ΠΊΠΎΠ΄Π° ошибки Π² тСкст:

function preg_errtxt($errcode)
{
    static $errtext;
    if (!isset($errtxt))
    {
        $errtext = array();
        $constants = get_defined_constants(true);
        foreach ($constants['pcre'] as $c => $n) if (preg_match('/_ERROR$/', $c)) $errtext[$n] = $c;
    }
    return array_key_exists($errcode, $errtext)? $errtext[$errcode] : NULL;
}

О бСзопасности.

ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ Β«eΒ»

e - ΠΎΠ±ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ evil eval. ΠŸΡ€ΠΈ использованиС Π΅Π³ΠΎ с preg_replace() функция Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ подстановку ΠΏΠΎ рСгулярному Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΡŽ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ Π΅Π³ΠΎ ΠΊΠ°ΠΊ PHP-ΠΊΠΎΠ΄.

$input = 'up this case!';
$output = preg_replace('/\w+/e', 'strtoupper($0)', $input);
echo $output; // UP THIS CASE!

Но, это ΡƒΠΆΠ΅ история ΠΈ с /e Ρ‚Ρ‹ скорСС всСго ΡΡ‚ΠΎΠ»ΠΊΠ½Π΅ΡˆΡŒΡΡ, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ссли Π±ΡƒΠ΄Π΅ΡˆΡŒ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с Π΄Ρ€Π΅Π²Π½ΠΈΠΌ лСгаси ΠΊΠΎΠ΄ΠΎΠΌ! ИспользованиС этого ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π° Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Ρ‡Π΅Π½ΠΎ ΠΊΠ°ΠΊ deprecated начиная с PHP 5.5, Π° Π² PHP 7 Π΅Π³ΠΎ ΡƒΠ΄Π°Π»ΠΈΠ»ΠΈ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ.

ВмСсто /e стоит ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ preg_replace_callback(), ΠΎ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ я писал Ρ€Π°Π½Π΅Π΅:

$input = 'up this case!';

$output = preg_replace_callback('/\w+/', function($m) {
    return strtoupper($m[1]);
}, $input);
echo $output; // UP THIS CASE!

ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ. πŸ“

Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠΎΠ΄ - ΠΎΡ‡Π΅Π½ΡŒ Ρ…ΠΎΡ€ΠΎΡˆΠ°Ρ ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ°. Π’Π°ΠΊ ΠΆΠ΅, Π½Π΅ стоит ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ ΠΏΡ€ΠΈ написании рСгулярных Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ.

eXtended mode

Π­Ρ‚ΠΎ ΠΏΡ€Π΅Π΄ΠΏΠΎΡ‡Ρ‚ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΈ Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ распространСнный способ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠ΅Π² с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π° x:

// Regex for password validation
$regex = '/
^                 # start-of-string
(?=.*[0-9])       # a digit must occur at least once
(?=.*[a-z])       # a lower case letter must occur at least once
(?=.*[A-Z])       # an upper case letter must occur at least once
(?=.*[@#$%^&+=])  # a special character must occur at least once
(?=\S+$)          # no whitespace allowed in the entire string
.{8,}             # anything, at least eight places though
$                 # end-of-string
/x';

ВсС Ρ‡Ρ‚ΠΎ ΠΈΠ΄Π΅Ρ‚ послС символа Ρ…Π΅ΡˆΡ‚Π΅Π³Π° игнорируСтся, Ρ‚Π°ΠΊ ΠΆΠ΅ ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ символы ΠΏΡ€ΠΎΠ±Π΅Π»Ρ‹. Из-Π·Π° этого Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ ΠΏΠΎΠ΄Π²ΠΎΠ΄Π½Ρ‹ΠΉ камСнь: ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΏΡ€ΠΎΠ±Π΅Π»Ρ‹ ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ, Ρ‡Ρ‚ΠΎ Π΄Π΅Π»Π°Ρ‚ΡŒ, Ссли Π½ΡƒΠΆΠ½ΠΎ ΡΠΌΠ°Ρ‚Ρ‡ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π΅Π»? Π•ΡΡ‚ΡŒ нСсколько способов:

  • Π­ΠΊΡ€Π°Π½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ±Π΅Π» $regex = '/\ +/x';
  • Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΈΠΌΠ²ΠΎΠ»ΡŒΠ½Ρ‹ΠΉ класс $regex = '/\s+/x

ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Ρ‹ шаблонов.

РСгулярныС выраТСния Π² PHP ΠΈΠΌΠ΅ΡŽΡ‚ мноТСство ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΎΠ². Π’ Π½Π΅ΠΌ Π΅ΡΡ‚ΡŒ Π΄Π°ΠΆΠ΅ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π½Π΅Ρ‚ Π² PCRE. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ, Π½Π°ΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΡŽ ΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΡ‚ΡŒΡΡ с Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠ΅ΠΉ.

ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ Β«iΒ»

Если установлСн этот ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€, Ρ‚ΠΎ ΠΎΠ½ Π΄Π΅Π»Π°Π΅Ρ‚ шаблон Π½Π΅Ρ‡ΡƒΠ²ΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ ΠΊ рСгистру. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Ссли Ρƒ вас Π΅ΡΡ‚ΡŒ рСгулярка Π²ΠΈΠ΄Π° /[a-zA-Z0-9]+/, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡƒΠΏΡ€ΠΎΡΡ‚ΠΈΡ‚ΡŒ Π΅Π΅ Π΄ΠΎ /[a-z0-9]+/i. Π’ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Π²Ρ‹ Π½Π΅ Π·Π°Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ рСгулярку Π±ΠΎΠ»Π΅Π΅ Π³ΠΈΠ±ΠΊΠΎΠΉ.

ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ Β«sΒ»

Π’Π°ΠΊ ΠΆΠ΅ извСстСн ΠΊΠ°ΠΊ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€/Ρ€Π΅ΠΆΠΈΠΌ DOTALL. Если установлСн этот ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€, Ρ‚ΠΎ всС символы Ρ‚ΠΎΡ‡ΠΊΠΈ . Π±ΡƒΠ΄ΡƒΡ‚ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ Π’Π‘Π•ΠœΠ£, Π²ΠΊΠ»ΡŽΡ‡Π°Ρ символу Π½ΠΎΠ²ΠΎΠΉ строки. НапримСр /a.*b/ Π±ΡƒΠ΄Π΅Ρ‚ ΠΌΠ°Ρ‚Ρ‡ΠΈΡ‚ΡŒ:

a test b

Но, Π½Π΅ сматчит

a test
test b

Однако, /a.*b/s сматчит ΠΎΠ±Π° Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π°.

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ Ρ‚ΠΎΡ‡ΠΊΠ° Π² классС символов [.] тСряСт своС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈ ΠΎΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚ΠΎΠ²Π°Ρ‚ΡŒ Π±ΡƒΠΊΠ²Π°Π»ΡŒΠ½ΠΎ Ρ‚ΠΎΡ‡ΠΊΠ΅.

ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ Β«mΒ»

Π’Π°ΠΊ ΠΆΠ΅ извСстСн ΠΊΠ°ΠΊ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€/Ρ€Π΅ΠΆΠΈΠΌ MULTILINE. Π¦ΠΈΡ‚Π°Ρ‚Π° ΠΈΠ· Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ:

By default, PCRE treats the subject string as consisting of a single “line” of characters (even if it actually contains several newlines). The “start of line” metacharacter ^ matches only at the start of the string, while the “end of line” metacharacter $ matches only at the end of the string, or before a terminating newline (unless D modifier is set). This is the same as Perl. When this modifier is set, the “start of line” and “end of line” constructs match immediately following or immediately before any newline in the subject string, respectively, as well as at the very start and end. This is equivalent to Perl’s /m modifier. If there are no \n characters in a subject string, or no occurrences of ^ or $ in a pattern, setting this modifier has no effect.

Π§Ρ‚ΠΎ это Π·Π½Π°Ρ‡ΠΈΡ‚ Π½Π° ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ΅? Допустим ΠΌΡ‹ Ρ…ΠΎΡ‚ΠΈΠΌ Π½Π°ΠΉΡ‚ΠΈ ΠΎΠ΄Π½Ρƒ ΠΈΠ»ΠΈ нСсколько Ρ†ΠΈΡ„Ρ€ [0-9]+ Π² Π½Π°Ρ‡Π°Π»Π΅ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ строки. РСгулярка Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ /^[0-9]+/m. Π‘Π΅Π· ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π° /m рСгулярка Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ†ΠΈΡ„Ρ€Π°ΠΌ Π² ΠΏΠ΅Ρ€Π²ΠΎΠΉ строкС.

123     # Matched by /^[0-9]+/ and /^[0-9]+/m
1234    # Matched by /^[0-9]+/m
12345   # Matched by /^[0-9]+/m

ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ Β«uΒ»

Если этот ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ установлСн, Ρ‚ΠΎ входная строка ΠΈ regex ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ UTF-8. Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ со строками UTF-8 Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ этот ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€.

Π­Ρ‚ΠΎΡ‚ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ стоит Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ, Ссли Π²Ρ‹ Π½Π΅ ΡƒΠ²Π΅Ρ€Π΅Π½Ρ‹ Ρ‡Ρ‚ΠΎ Π±ΡƒΠ΄Π΅Ρ‚Π΅ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с ASCII (ΠΈΠ»ΠΈ ΠΎΠ΄Π½ΠΎΠ±Π°ΠΉΡ‚ΠΎΠ²Ρ‹ΠΌΠΈ Π½Π°Π±ΠΎΡ€Π°ΠΌΠΈ символов). ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ классы символов, Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ \w, \d, \s, \b, … становятся совмСстимыми с Unicode, ΠΊΠΎΠ³Π΄Π° этот ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ установлСн.

Π’Ρ‹Π±ΠΎΡ€ раздСлитСля.

ΠžΠ±Ρ‹Ρ‡Π½ΠΎ Π² качСствС раздСлитСля Π² рСгулярном Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ символ слСша (косой Ρ‡Π΅Ρ€Ρ‚Ρ‹) /. Но, ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Ρ€Π°Π·Π΄Π΅Π»ΠΈΡ‚Π΅Π»ΠΈ, особСнно Ссли Π² вашСм рСгулярном Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π΅ΡΡ‚ΡŒ ΠΌΠ½ΠΎΠ³ΠΎ символов слСша.

// Backslash
$regex = '/^\/user\/(\d+)\/?/i';

// Clean
$regex = '~^/user/(\d+)/?~i';

Π”Ρ€ΡƒΠ³ΠΈΠΌΠΈ раздСлитСлями ΡΠ²Π»ΡΡŽΡ‚ΡΡ символы #,!,%,_,;. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Ρ‚ΠΎΡ‚, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ с мСньшСй Π²Π΅Ρ€ΠΎΡΡ‚Π½ΠΎΡΡ‚ΡŒΡŽ Π±ΡƒΠ΄Π΅Ρ‚ часто Π²ΡΡ‚Ρ€Π΅Ρ‡Π°Ρ‚ΡŒΡΡ Π² вашСм рСгулярном Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΈ. НапримСр # ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ x для ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠ΅Π² ΠΈΠ»ΠΈ ΠΊΠΎΠ³Π΄Π° Ρƒ вас просто Π΅ΡΡ‚ΡŒ рСгулярка с ΠΎΠ΄Π½ΠΈΠΌ ΠΈΠ· этих символов.

Одним ΠΈΠ· Π½Π΅ ΠΎΡ‡Π΅Π½ΡŒ извСстных, Π½ΠΎ интСрСсных способов являСтся использованиС ассимСтричной ΠΏΠ°Ρ€Ρ‹ Ρ€Π°Π·Π΄Π΅Π»ΠΈΡ‚Π΅Π»Π΅ΠΉ, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ ():

$regex = '(^/user/(\d+)/?)i';

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, скобки Π²Π½ΡƒΡ‚Ρ€ΠΈ рСгулярки Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ ΡΠΊΡ€Π°Π½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ. Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Ρ€Π°ΡΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒ ΠΏΠ΅Ρ€Π²Ρ‹Π΅ скобки ΠΊΠ°ΠΊ Β«Π³Ρ€ΡƒΠΏΠΏΡƒ 0Β», Π° Π²Ρ‚ΠΎΡ€Ρ‹Π΅ (Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠ΅ скобки) ΠΊΠ°ΠΊ Β«Π³Ρ€ΡƒΠΏΠΏΡƒ 1Β».

Π—Π½Π°ΠΉ Ρ‡Ρ‚ΠΎ Π½ΡƒΠΆΠ½ΠΎ ΡΠΊΡ€Π°Π½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ.

Иногда, Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ символы Π½Π΅ Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ экранированиС. И часто использования экранирования сильно Π·Π°ΠΏΡƒΡ‚Ρ‹Π²Π°Π΅Ρ‚ ΠΈ затрудняСт Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ рСгулярного выраТСния.

// НСпонятно
$regex = '~\>\>user\d+\,\ \"\d+\-\d+\"~';

// ΠŸΠΎΠ½ΡΡ‚Π½ΠΎ
$regex = '~>>user\d+, "\d+-\d+"~';

Π§Ρ‚ΠΎ Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ ΡΠΊΡ€Π°Π½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ?

  • Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ символы <>@!#~=_,'", Ссли ΠΎΠ½ΠΈ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ Π² качСствС раздСлитСля.
    • /<>@!#~=_,'"/ сматчит <>@!#~=_,'".
  • ΠŸΡ€ΠΎΠ±Π΅Π»Ρ‹, Ссли Ρ‚Ρ‹ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΡˆΡŒ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ x.
  • ДСфисы Π²Π½Π΅ Π³Ρ€ΡƒΠΏΠΏΡ‹ символов.
    • /-+/ сматчит ΠΎΠ΄ΠΈΠ½ ΠΈΠ»ΠΈ Π±ΠΎΠ»Π΅Π΅ дСфисов.
  • ДСфисы Π²Π½ΡƒΡ‚Ρ€ΠΈ Π³Ρ€ΡƒΠΏΠΏΡ‹ символов Π² Π½Π°Ρ‡Π°Π»Π΅ ΠΈ Π² ΠΊΠΎΠ½Ρ†Π΅.
    • /[a-z-]+/ Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Ρƒ Π±ΡƒΠΊΠ² ΠΎΡ‚ a Π΄ΠΎ z, Π²ΠΊΠ»ΡŽΡ‡Π°Ρ дСфис. ΠŸΡ€ΠΈΠΌΠ΅Ρ€: abcde-fgh.
    • /[-a-z]+/ Ρ‚ΠΎΠΆΠ΅ самоС Ρ‡Ρ‚ΠΎ ΠΈ Π²Ρ‹ΡˆΠ΅.