Доллар в регвыражениях не всегда означает конец строки
Долго боролся сейчас с одним багом, поэтому пишу себе, чтобы не забыть.
Есть регулярное выражение (для примера):
/(some|any)thing$/i
Доллар, уверен я, означает «конец строки». Выражение должно проверять, что строка заканчивается на слово something или anything в любом регистре. Но вот оно иногда срабатывает, даже если строка не заканчивается на него! Я в отчаянии уже проверяю впрямую, что строка заканчивается на g или G, и точно вижу, что она не заканчивается. А выражение срабатывает!
Замечаю, что это происходит, если в конце выражения стоит возврат каретки. Думаю: какого хрена? У меня же написан доллар сразу после g, никаких возвратов каретки там! Модификатора /m, который разделяет текст на отдельные строки, нет. Может, он как-то там по умолчанию включился, и надо его, наоборот, отключить?
От безысходности иду читать документацию. Никакого антонима модификатору /m не нахожу. Читаю про сам /m:
m (PCRE_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).
Что? Что ещё за нахрен /D?
D (PCRE_DOLLAR_ENDONLY)
If this modifier is set, a dollar metacharacter in the pattern matches only at the end of the subject string. Without this modifier, a dollar also matches immediately before the final character if it is a newline (but not before any other newlines).
Как же можно было такую дичь придумать? Исправляю регулярное выражение:
/(some|any)thing$/iD
А также запоминаю, что надо теперь вообще всегда использовать модификатор /D, потому что если блин мне надо возврат каретки мэтчить, я это в состоянии впрямую сформулировать внутри регвыражения, а не полагаться на это хитрожопое исключение.
Как будто всё остальное в PHP сделано хоть немножко разумно... (Вон даже в документации — «dollar metacharacter» вместо «$ metacharacter» — чтобы никто поиском не нашёл.)
Я рад, что вам не нравится ПХП, но язык регулярных придумали не авторы ПХП — это из Перла.
Язык регулярных выражений придумали задолго до Перла, а в Перле он был расширен до более практичного (поэтому это называется именно «PCRE», не просто «RE», которые гораздо беднее). В отличие от ПХП, у Перла есть вменяемая документация (https://perldoc.perl.org/perlretut), в которой прямо написано про поведение по умолчанию («’.’ matches any character except „\n“ ... ’$’ matches only at the end or before a newline at the end») и почему оно наиболее разумно для языка, разработанного для обработки текстовых файлов, обычно построчной. В том же разделе (в пределах одной экранной страницы, с подробными примерами) описаны модификаторы «/s» и «/m», а также разница между «$», «\Z» и «\z» (последний как раз «matches only the end»).
Что невменяемого в документации ПХП? Я ж её процитировал, в ней тоже это написано. Проблема не в документации, а в дизайне.