реализация регулярного выражения для замены группы ее строчной версией


Существует ли реализация регулярного выражения, позволяющая заменить группу в регулярном выражении на его строчную версию?

6 45

6 ответов:

В Perl вы можете сделать:

$string =~ s/(some_regex)/lc($1)/ge;

Параметр /e заставляет выражение замены интерпретироваться как вычисляемый код Perl, возвращаемое значение которого используется в качестве конечного значения замены. lc($x) возвращает строчную версию $x. (Не уверен, но я предполагаю, что lc() будет корректно обрабатывать международные символы в последних версиях Perl.)

/g значит совпадают глобально. Опустите g, если требуется только одна замена.

Если ваша версия regex поддерживает его, вы можете использовать \L, как в POSIX-оболочке:

sed -r 's/(^.*)/\L\1/'

Если вы используете редактор типа SublimeText или TextMate1, есть хороший шанс, что вы можете использовать

\L$1

В качестве замены, где $1 относится к чему-то из регулярного выражения, которое вы заключаете в скобки. Например:2, вот то, что я использовал для понижения имен полей в некоторых SQL, получая все справа от " as " в конце любой заданной строки. Сначала регулярное выражение" найти":

(as|AS) ([A-Za-z_]+)\s*,$

А затем замена выражение:

$1 '\L$2',

Если вы используете Vim (или предположительно gvim), то вы захотите использовать \L\1 вместо \L$1, но есть еще одна особенность, о которой вам нужно знать: Vim меняет синтаксис между буквальными символами скобок и экранированными символами скобок. Поэтому для обозначения части регулярного выражения, которая должна быть включена в замену ("захвачена"), вы будете использовать \( в начале и \) в конце. Подумайте о \ как-вместо того, чтобы избежать специального символа, чтобы сделать это литерал-маркировка начала специального символа (как с \s, \w, \b и так далее). Так что это может показаться странным, если вы к этому не привыкли, но на самом деле это совершенно логично, если вы думаете об этом в Vim-ключе.


1 я проверил это как в TextMate, так и в SublimeText, и это работает как есть, но некоторые редакторы используют \1 вместо $1. Попробуйте оба варианта и посмотрите, какие из них использует ваш редактор.

2 я просто вытащил это регулярное выражение из своей истории. Я всегда я не могу обещать, что это окончательная версия, поэтому я не предполагаю, что она подходит для описанной цели, и особенно не с SQL, отформатированным иначе, чем SQL, над которым я работал, просто это конкретный пример понижения в регулярных выражениях. YMMV. УАЙОР.

Несколько ответов отметили использование \L. Однако \E Также стоит знать, если вы используете \L.

\L преобразует все до следующего \U или \E в нижний регистр. ... \E отключает преобразование регистра.

(Источник: https://www.regular-expressions.info/replacecase.html )

Итак, предположим, вы хотите использовать rename чтобы заглавная часть некоторых имен файлов выглядела так:

artist_-_album_-_Song_Title_to_be_Lowercased_-_MultiCaseHash.m4a
artist_-_album_-_Another_Song_Title_to_be_Lowercased_-_MultiCaseHash.m4a

Вы могли бы сделать что-то вроде:

rename -v 's/^(.*_-_)(.*)(_-_.*.m4a)/$1\L$2\E$3/g' *

В Perl есть

$string =~ tr/[A-Z]/[a-z]/;

Большинство реализаций регулярных выражений позволяют передавать функцию обратного вызова при выполнении замены, поэтому вы можете просто вернуть строчную версию соответствия из обратного вызова.