Использование регулярных выражений для поиска любого последнего вхождения слова между двумя разделителями
Предположим, у меня есть следующая тестовая строка:
Start_Get_Get_Get_Stop_Start_Get_Get_Stop_Start_Get_Stop
где _ означает любые символы, например: StartaGetbbGetcccGetddddStopeeeeeStart....
Что я хочу извлечь, так это любое последнее вхождение слова Get в разделители Start и Stop. Результатом здесь будет три полужирных Get ниже.
Start__Get__Get__Get__Stop__Start__Get__Get__Stop__Start__Get__Stop
Я уточнил, что хотел бы сделать это только с помощью регулярных выражений и насколько это возможно за один проход.
Любые предложения приветствуются
Спасибо'
5 ответов
Get(?=(?:(?!Get|Start|Stop).)*Stop)
Я предполагаю, что ваш Start
а также Stop
Разделители всегда будут правильно сбалансированы и не могут быть вложенными.
Я бы сделал это с двумя проходами. На первом проходе найдите слово "Get", а на втором проходе посчитайте количество его появлений.
$ echo "Start_Get_Get_Get_Stop_Start_Get_Get_Stop_Start_Get__Stop" | awk -vRS="Stop" -F"_*" '{print $(NF-1)}'
Get
Get
Get
С Perl я бы сделал:
my $test = "Start_Get_Get_Get_Stop_Start_Get_Get_Stop_Start_Get_Stop";
$test =~ s#(?<=Start_)((Get_)*)(Get)(?=_Stop)#$1<FOUND>$3</FOUND>#g;
print $test;
выход:
Start_Get_Get_<FOUND>Get</FOUND>_Stop_Start_Get_<FOUND>Get</FOUND>_Stop_Start_<FOUND>Get</FOUND>_Stop
Вы должны адаптироваться к своему вкусу регулярных выражений.
Примерно так, может быть:
(?<=Start(?:.Get)*)Get(?=.Stop)
Для этого требуется поддержка просмотра за разную длину, которую поддерживают не все движки регулярных выражений.
Можно сделать так, чтобы иметь максимальную длину, которую поддерживают еще несколько (но не все), изменив первую *
в {0,99}
или похожие.
Кроме того, в перспективе, возможно, .
должен быть .+
или же .{1,2}
в зависимости от того, является ли двойное подчеркивание опечаткой или нет.