Регулярное выражение не выполняется, когда шаблон включает знак доллара ($)
Я сталкиваюсь с небольшой проблемой, когда дело доходит до сопоставления подшаблонов, которые включают знак доллара. Например, рассмотрим следующий фрагмент текста:
Regular Price: $20.50 Final Price: $15.20
Regular Price: $18.99 Final Price: $2.25
Regular Price: $11.22 Final Price: $33.44
Regular Price: $55.66 Final Price: $77.88
Я пытался сопоставить обычные/окончательные наборы цен со следующим регулярным выражением, но это просто не работало (никаких совпадений вообще):preg_match_all("/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U", $data, $matches);
Я избежал знака доллара, так что же получается?
2 answers
Внутри строки в двойных кавычках обратная косая черта рассматривается как escape-символ для $
. Обратная косая черта удаляется синтаксическим анализатором PHP еще до того, как функция preg_match_all
ее увидит:
$r = "/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U";
var_dump($r);
Вывод (идеон):
"/Regular Price: $(\d+\.\d{2}).*Final Price: $(\d+\.\d{2})/U" ^ ^ the backslashes are no longer there
Чтобы исправить это, используйте строку в одинарных кавычках вместо строки в двойных кавычках:
preg_match_all('/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U',
$data,
$matches);
Посмотрите, как он работает онлайн: ideone
Я знаю, что этот вопрос немного устарел, но я нашел это, пытаясь найти ответ на ту же проблему. Я увидел, что он находится на вершине рейтинга поисковых систем, поэтому решил, что было бы неплохо объяснить простую альтернативу и почему это происходит со строками в двойных кавычках ( " )
Регулярное выражение, которое я использовал, содержало в себе множество символов в одинарных кавычках ( ' )
, поэтому я не слишком стремился обернуть выражение ими, так как не хотел избегать всего из тех.
Мое решение состояло в том, чтобы "дважды избежать" знака доллара. В вашем примере это должно выглядеть примерно так:
"/Regular Price: \\\$(\d+\.\d{2}).*Final Price: \\\$(\d+\.\d{2})/U";
Обратите внимание, что знак доллара теперь содержит 3 косых черты \\\
.
В принципе, у нас есть два "уровня" интерпретации: PHP и выражение регулярного выражения. Что происходит, так это то, что с одной косой чертой PHP интерпретирует ее как буквальный символ вместо модификатора переменной, поэтому он съедает косую черту, интерпретирует строку, как описано в ответ, а затем отправляет его в регулярное выражение, которое интерпретируется как взгляд назад.
"дважды избегая" знака доллара, PHP интерпретирует \\\$
как \\
и \$
соответственно. Мы экранируем \
из первого набора символов и экранируем $
из второго набора, в результате чего получаем только \$
после интерпретации PHP. Это отправит литеральную строку
"/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U";
Для регулярного выражения, которое будет интерпретировать \$
как символьный литерал $
, который будет соответствовать $
вместо того, чтобы действовать как взгляд назад, так как он ускользнул. Здесь важно понимать двойные уровни интерпретации, поскольку и PHP, и регулярное выражение имеют свои собственные правила интерпретации, и для правильного экранирования символов может потребоваться до 4 косых черт.
Строки в одинарных кавычках не имеют этой проблемы, так как для использования переменной $foo
в строке нам пришлось бы написать
'Hello '. $foo .'!';
Вместо
"Hello $foo!";
Как мы можем в двойных строках. В отличие от строк в двойных кавычках, строки в одинарных кавычках не могут интерпретируйте переменные внутри строки как переменные (если они не добавлены, как в примере выше), вместо этого интерпретируйте их как обычный текст. Поскольку нам больше не нужно экранировать переменную, мы можем обойтись просто
'/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U'
, который отправит \$
в регулярное выражение, такое же, как и с \\\$
в строке с двойными кавычками.
Все зависит от личных предпочтений, какой стиль вы используете или какой проще для шаблона.
TL;DR: Используйте \$
для строк в одинарных кавычках, таких как '/Hello \$bob/is'
и \\\$
для строк в двойных кавычках, таких как "/Hello \\\$bob/is"
.