с помощью команды 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"


Любые дальнейшие предложения по-прежнему приветствуются :)

569   3  

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 использует скрытое утверждение, чтобы вывести только цифру, следующую за буквой "А". Это работает с GNU grep -Po, ack -o, и pcregrep -o. Утверждение имеет нулевую ширину, поэтому оно не включается в матч.

Вы можете использовать Perl напрямую, получая доступ к переменным окружения через хэш %ENV:

perl -lwe 'print $ENV{var} =~ /a(\d+)/;'

Он будет печатать только захват, внутри скобок.

Comments

    Ничего не найдено.