Regex не работает, когда шаблон включает знак доллара ($)

Я сталкиваюсь с проблемой, когда речь идет о подшаблонах, которые включают знак доллара. Например, рассмотрим следующий фрагмент текста:

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);

Я избежал знака доллара, так что дает?

Внутри строки с двойными кавычками обратная косая черта рассматривается как escape-символ для $ . Обратная косая черта удаляется парсером PHP еще до того, как видит функция preg_match_all :

 $r = "/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U"; var_dump($r); 

Выход ( идеал ):

 "/ Обычная цена: $ (\ d + \. \ D {2}). * Окончательная цена: $ (\ d + \. \ D {2}) / U"
                  ^ ^
               обратной косой черты больше нет

Чтобы исправить это, используйте одну строку с кавычками вместо строки с двойными кавычками:

 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' 

который отправит \$ в regex, так же, как и \\\$ в строке двойной кавычки.

Все зависит от личных предпочтений от того, какой стиль вы используете, или который проще для шаблона.

TL; DR: используйте \$ для строк с одним кавычком, например '/Hello \$bob/is' , и \\\$ для строк с двойными кавычками, таких как "/Hello \\\$bob/is" .