Você não pode ter o GNU grep -o
com o mesmo texto (como meaning n words before the
ou and n words after the
) duas vezes. Você poderia fazer isso com pcregrep
usando -o<n>
, em que n
é o grupo de captura n
th e capturar o que é correspondido em um operador look ahead (que não avança o cursor para o próximo jogo):
$ pcregrep -o0 -o2 '(\w+\W+){0,5}token(?=((\W+\w+){0,5}))' file
This is a token, but when any punctuation is
n words around a specific token, meaning n words before the
meaning n words before the token and n words after the
and n words after the token. There is no fix pattern
-o0
corresponde a todo o texto, -o1
corresponde ao (....)
no operador (?=(here))
look-ahead.
Observe que em uma entrada como:
6 5 4 3 2 1 token token 1 2 3 4 5 6
daria:
5 4 3 2 1 token token 1 2 3 4
token 1 2 3 4 5
porque começa a procurar a segunda correspondência logo após o primeiro token , portanto, encontra apenas 0
palavras antes da segunda token
.
$ echo 6 5 4 3 2 1 token token 1 2 3 4 5 6 |
pcregrep -o1 '(?=((\w+\W+){0,5}token(\W+\w+){0,5}))\w*'
5 4 3 2 1 token token 1 2 3 4
4 3 2 1 token token 1 2 3 4 5
3 2 1 token token 1 2 3 4 5
2 1 token token 1 2 3 4 5
1 token token 1 2 3 4 5
token token 1 2 3 4 5
token 1 2 3 4 5
Provavelmente não seria o que você deseja (mesmo que cada um seja "token" precedido e seguido por até cinco palavras).
Para obter uma linha para cada ocorrência de "token" com até cinco palavras em ambos os lados, não acho que você faça isso facilmente com pcregrep
sozinho.
Você precisaria registrar a posição de cada palavra "token" e então combinar o up-to-5-words<that-position>"token"up-to-5-words
para cada uma dessas posições.
Algo como:
$ echo 6 5 4 3 2 1 token token 1 2 3 4 5 6 | perl -lne '
my @positions; push @positions, $-[0] while /\btoken\b/g;
for $o (@positions) {
print $& if /(\w+\W+){0,5}(?<=^.{$o})token(\W+\w+){0,5}/
}'
5 4 3 2 1 token token 1 2 3 4
4 3 2 1 token token 1 2 3 4 5
Ou para esclarecer qual token está sendo correspondido em cada caso:
$ echo 6 5 4 3 2 1 token token 1 2 3 4 5 6 | perl -lne '
my @positions; push @positions, $-[0] while /\btoken\b/g;
for $o (@positions) {
print "$1<token>$3" if /((\w+\W+){0,5})(?<=^.{$o})token((\W+\w+){0,5})/
}'
5 4 3 2 1 <token> token 1 2 3 4
4 3 2 1 token <token> 1 2 3 4 5
(Eu esperaria que pudesse ser simplificado / otimizado).