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

Есть ли какая-либо реализация регулярного выражения, которая позволяет заменить группу в регулярном выражении строчной версией?


person Community    schedule 09.01.2009    source источник


Ответы (6)


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

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

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

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

person j_random_hacker    schedule 09.01.2009
comment
Perl также поддерживает синтаксис \L, например. s/(some_regex)/\L$1/g, проверено на 5.26. - person Ciro Santilli 新疆再教育营六四事件ۍ 25.04.2019

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

sed -r 's/(^.*)/\L\1/'
person Kim    schedule 15.05.2009
comment
Похоже, это работает в удивительном количестве наборов регулярных выражений, даже если вы не находитесь в среде, похожей на оболочку. - person Tim; 27.06.2013
comment
@Tim: Согласен, даже Notepad++ поддерживает это. - person Nelson Rothermel; 15.08.2013
comment
Это не работает в zsh или bash на OSX (да, я использую -E вместо -r). - person dcow; 21.12.2014
comment
BSD sed слишком ограничен. В OS X используйте Homebrew и вместо этого установите gnu-sed. Тогда это работает. - person Kim; 22.12.2014
comment
Работает в команде Linux rename, которая, по крайней мере, в Ubuntu 14 является Perl-скриптом (/usr/bin/prename). - person Camille Goudeseune; 15.06.2015
comment
Поскольку * является жадным, а . обозначает любой символ, вам не нужно привязывать шаблон к ^. С помощью gnu sed вы также можете удалить группу захвата и ключ -r и написать: sed 's/.*/\L&/'. С другой стороны, запись sed --posix 's/\(.*\)/\L\1/' не работает с gnu sed (и добавьте L в начале строки). - person Casimir et Hippolyte; 28.10.2017

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

\L$1

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

(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. УАЙОР.

person iconoclast    schedule 23.01.2014
comment
Хорошо, Intellij IDEA поддерживает и это. - person Pieter De Bie; 03.12.2017

В нескольких ответах отмечено использование \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' *
person Community    schedule 22.03.2018

В Перле есть

$string =~ tr/[A-Z]/[a-z]/;
person Hank Gay    schedule 09.01.2009
comment
[А-Я]? Это был пример. Тем не менее, я проголосовал за ответ j_random_hacker. - person Hank Gay; 09.01.2009

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

person AnthonyWJones    schedule 09.01.2009