“preg_match(): Compilation failed: unmatched paren

2020-08-13 09:45发布

问题:

Wondering if anyone out there can shed some light on why the following regular expression is failing when used in PHP's preg_match function:-

<?php
$str = '\tmp\phpDC1C.tmp';

preg_match('|\\tmp\\([A-Za-z0-9]+)|', $str, $matches);

print_r($matches);
?>

This results in the error message "preg_match(): Compilation failed: unmatched parentheses" despite the fact that the pattern appears to be valid. I've tested it with an online PHP Regular Expression tester and the Linux tool Kiki. Seems like PHP is escaping the opening parenthesis rather than the backslash.

I've got round the issue by using str_replace to swap the backslashes for forward ones. This works for my situation but it would be nice to know why this regular expression is failing.

回答1:

To encode a literal backslash, you need to escape it twice: Once for the string, and once for the regex engine:

preg_match('|\\\\tmp\\\\([A-Za-z0-9]+)|', $str, $matches);

In PHP (when using single-quoted strings), this is only relevant for actual backslashes; other regex escapes are OK with a single backslash:

preg_match('/\bhello\b/', $subject)

This is covered in the manual (see the box labeled "Note:" at the top of the page).



回答2:

you have to use |\\\tmp\\\([A-Za-z0-9]+)| expression

but there are better way to get file name because of concrete form of string. for example:

substr($str, 5, -4);

think about memory usage



回答3:

strange I just tested using the same online regex tester which you mentioned and it compiled without error :

<?php 
$ptn = "/<;?php $str = '\tmp\phpDC1C.tmp'; 
preg_match('|\\tmp\\([A-Za-z0-9]+)|', $str, $matches); print_r($matches); ?>;/";
$str = "";
preg_match($ptn, $str, $matches);
print_r($matches);
?>


回答4:

Use the next regex:

php >$str = '\tmp\phpDC1C.tmp'; 
php >preg_match('/[\\\\]tmp[\\\\]([A-Za-z0-9]+)/', $str, $matches);
php >print_r($matches);
Array
(
  [0] => \tmp\phpDC1C
  [1] => phpDC1C
)