с помощью команды grep в Linux с Perl регулярных выражений + захват группы
Итак, я провел некоторые исследования на эту тему, и я не совсем нашел идеальное решение.
Например, у меня есть строка внутри переменной.
var="a1b1c2"
Теперь то, что я хочу сделать, это сопоставить только "a", следующий за любой цифрой, но я хочу, чтобы он только вернул число после "a"
Чтобы соответствовать ему правило, такое как
'ad'
И поскольку мне нужна только цифра, я попробовал с
'a(d)'
И, возможно, он действительно захватил его где-то, но я не знаю, где, выход здесь все еще "a1"
I кроме того, группа без захвата пыталась игнорировать "a" в выходных данных, но никакого эффекта в регулярном выражении perl:
'(?:a)d'
Для справки, это полная команда в моем терминале:
[root@host ~]# var="a1b1c2"
[root@host ~]# echo $var |grep -oP "a(d)"
a1 <--output
Вероятно, это также возможно без-P (некоторые не-perl regex формат), я благодарен за каждый ответ:)
Редактировать:
использование
K
На самом деле это не решение, так как мне не обязательно нужна последняя часть матча.
EDIT2:
Мне нужно иметь возможность получить любой часть матча, например:
[root@host ~]# var="a1b1c2"
[root@host ~]# echo $var |grep -oP "(a)d"
a1 <--output
but the wanted output in this case would be "a"
EDIT3:
Проблема почти решена с помощью "скрытых утверждений", таких как:
(?<=a)d
Не вернет букву "а", только следующую за ней цифру, но ей нужна фиксированная длина, например ее нельзя использовать как:
(?<=w+)d
EDIT4:
Лучший способ до сих пор-либо использовать perl, либо комбинировать комбинацию look-behind утверждений и K, но он все еще, кажется, имеет некоторые ограничения. Для пример:
1234_foo_1234_bar
1234567_foo_123456789_bar
1_foo_12345_bar
if "foo" and "bar" are place-holders for words that don't always have the same length,
there is no way to match all above examples while output "foobar", since the
number between them doesn't have a fixed length, while it can't be done with K since we need "foo"
Любые дальнейшие предложения по-прежнему приветствуются :)
3 ответов:
После некоторого тестирования я обнаружил, что шаблон внутри утверждения look-behind должен быть фиксированной длины (что-то вроде
(?<=\w+)somethingне будет работать, какие-либо предложения?Поскольку я опубликовал и удалил свой ответ ранее, потому что вы заявили, что он не соответствует вашим потребностям:
Большую часть времени, вы можете избежать lookbehinds переменной длины с помощью
Ключевое различие между использованием\K. Это сбрасывает начальную точку сообщенного совпадения, и все ранее использованные символы больше не используются. включенный. (отбрасывает все, что соответствовало этому моменту.)\Kи lookbehind заключается в том, что lookbehind не позволяет использовать кванторы: длина того, что вы ищете, должна быть фиксированной. Но\Kможно поместить в любом месте шаблона, поэтому вы можете использовать любые кванторы.Как вы можете видеть в приведенном ниже примере, использование квантора в lookbheind не будет работать.
echo 'foosomething' | grep -Po '(?<=\w+)something' #=> grep: lookbehind assertion is not fixed lengthИтак, вы мог бы сделать:
echo 'foosomething' | grep -Po '\w+\Ksomething' #=> somethingЧтобы получить подстроку только между двумя шаблонами, вы можете добавить положительный Lookahead в смесь.
echo 'foosomethingbar' | grep -Po 'foo\K.*?(?=bar)' #=> somethingИли используется фиксированный Lookbehind в сочетании с Lookahead.
echo 'foosomethingbar' | grep -Po '(?<=foo).*?(?=bar)' #=> something
Шаблон
(?<=a)\dиспользует скрытое утверждение, чтобы вывести только цифру, следующую за буквой "А". Это работает с GNUgrep -Po,ack -o, иpcregrep -o. Утверждение имеет нулевую ширину, поэтому оно не включается в матч.
Вы можете использовать Perl напрямую, получая доступ к переменным окружения через хэш
%ENV:perl -lwe 'print $ENV{var} =~ /a(\d+)/;'Он будет печатать только захват, внутри скобок.
Comments