Digamos que eu tenho um arquivo:
# file: 'test.txt'
foobar bash 1
bash
foobar happy
foobar
Eu só quero saber que palavras aparecem depois de "foobar" para que eu possa usar este regex:
"foobar \(\w\+\)"
Os parênteses indicam que eu tenho um interesse especial na palavra logo após o foobar. Mas quando eu faço um 'grep "foobar; test.txt', eu recebo as linhas inteiras que correspondem a todo o regex, em vez de apenas " a palavra depois de foobar":
foobar bash 1
foobar happy
Eu preferia que a saída desse comando fosse parecida com esta:
bash
happy
Existe alguma forma de dizer ao grep que apenas os itens que combinam com o agrupamento (ou um agrupamento específico) devem sair em uma expressão regular?
O GNU grep tem a opção -P' para regexes no estilo perl, e a opção
-o' para imprimir apenas o que combina com o padrão. Elas podem ser combinadas utilizando asserções look-around (descritas em Extended Patterns in the perlre manpage) para remover parte do padrão do grep do que é determinado como tendo correspondido para os propósitos de -o
.
$ grep -oP 'foobar \K\w+' test.txt
bash
happy
$
O \K' é a forma curta (e mais eficiente) de
(?<=padrão)que você utiliza como uma afirmação de largura zero antes do texto que você quer produzir.
(?=padrão)` pode ser utilizado como uma asserção de olhar para a frente com largura zero depois do texto que você quer produzir.
Por exemplo, se você quisesse combinar a palavra entre foo
e bar
, você poderia usar:
$ grep -oP 'foo \K\w+(?= bar)' test.txt
ou (por simetria)
$ grep -oP '(?<=foo )\w+(?= bar)' test.txt
O grep pode't fazer isto, mas versões recentes do GNU grep podem. Você pode virar para sed, awk ou perl. Aqui estão alguns exemplos que fazem o que você quer no seu exemplo de entrada; eles se comportam de forma ligeiramente diferente em casos de canto.
Substitua a palavra "outro material" por "palavra", imprima apenas se for feita uma substituição.
sed -n -e 's/^foobar \([[:alnum:]]\+\).*/\1/p'
Se a primeira palavra é foobar
, imprima a segunda palavra.
awk '$1 == "foobar" {print $2}'
Tire a primeira palavra, se for'é a primeira palavra, e pule a linha caso contrário; depois tire tudo depois do primeiro espaço em branco e imprima.
perl -lne 's/^foobar\s+// or next; s/\s.*//; print'