In the top-voted answer to this fantastic question, the following regular expression is used in a preg_replace
call (from the answer's auto_version
function):
'{\\.([^./]+)$}'
The end goal of this regular expression is to extract the file's extension from the given filename. However, I'm confused about why the very beginning of this regular expression works. Namely:
Why does \\.
match the same way as \.
in a regex?
Shouldn't the former match (a) one literal backslash, followed by (b) any character, while the second matches one literal period? The rules for single quoted strings state that \\
yields a literal backslash.
Consider this simple example:
$regex1 = '{\.([^./]+)$}'; // Variant 1 (one backslash)
$regex2 = '{\\.([^./]+)$}'; // Variant 2 (two backslashes)
$subject1 = '/css/foobar.css'; // Regular path
$subject2 = '/css/foobar\\.css'; // Literal backslash before period
echo "<pre>\n";
echo "Subject 1: $subject1\n";
echo "Subject 2: $subject2\n\n";
echo "Regex 1: $regex1\n";
echo "Regex 2: $regex2\n\n";
// Test Variant 1
echo preg_replace($regex1, "-test.\$1", $subject1) . "\n";
echo preg_replace($regex1, "-test.\$1", $subject2) . "\n\n";
// Test Variant 2
echo preg_replace($regex2, "-test.\$1", $subject1) . "\n";
echo preg_replace($regex2, "-test.\$1", $subject2) . "\n\n";
echo "</pre>\n";
The output is:
Subject 1: /css/foobar.css
Subject 2: /css/foobar\.css
Regex 1: {\.([^./]+)$} <-- Output matches regex 2
Regex 2: {\.([^./]+)$} <-- Output matches regex 1
/css/foobar-test.css
/css/foobar\-test.css
/css/foobar-test.css
/css/foobar\-test.css
Long story short: why should \\.
yield the same matched results in a preg_replace
call as \.
?