Доллар в регвыражениях не всегда означает конец строки
Долго боролся сейчас с одним багом, поэтому пишу себе, чтобы не забыть.
Есть регулярное выражение (для примера):
/(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, потому что если блин мне надо возврат каретки мэтчить, я это в состоянии впрямую сформулировать внутри регвыражения, а не полагаться на это хитрожопое исключение.