ENTRADA
AA XXX Y1Y ZZZ GG dhz
rr (AAAa) XXX Y2Y ZZZ TT GGGG UU
SAÍDA
Y1Y
Y2Y
As linhas de entrada podem variar.. apenas o XXX antes de Y1Y e o ZZZ depois de Y1Y são constantes (são vizinhos de XXX e ZZZ assim). Y1Y pode ser qualquer coisa, ex.: Y1Y, Y2Y, Y1T, etc.
P:como posso obter a SAÍDA com awk ou sed ou grep? (ou existe alguma ferramenta melhor para isso?)
ATUALIZAR(problema): por que não funciona quando se tem "." no Y1Y?
[user@notebook ~] echo 'XXX Y1Y ZZZ' | grep -Po "(?<=XXX )(\w+)(?= ZZZ)"
Y1Y
[user@notebook ~] echo 'XXX Y1.Y ZZZ' | grep -Po "(?<=XXX )(\w+)(?= ZZZ)"
[user@notebook ~]
Responder1
Você pode usar grep
o recurso PCRE fornecido para fazer isso:
$ grep -Po "(?<=XXX )\S+(?= ZZZ)" data.txt
Y1Y
Y2Y
Detalhes
Esta solução faz uso do recurso lookbehind e lookahead do PCRE, que pode corresponder a strings de comprimento fixo.
O texto acima olha atrás de cada um \w+
para ver se é XXX
e na cabeça de cada um \w+
para ver se é ZZZ
. Se for, então é uma correspondência. A -o
opção grep
diz para imprimir apenas as correspondências, ou seja \w+
, .
Acompanhamento, você pode fazer isso com sed?
Não creio que esse problema possa ser resolvido usando sed
. Existem 2 abordagens, a meu ver.
- salve possíveis correspondências em uma variável secundária, se você encontrar ZZZ, imprima-as
- s/XXX ..nossa string.. ZZZ/ ..nossa string../
O número 1 parece bastante trabalhoso, então nem vou tentar. Aqui está o que acontece com a abordagem nº 2.
$ sed 's/.*XXX \(.*\) ZZZ.*/\1/' data.txt
Y1Y
Y2Y
AAAa YXX Y2Y ZZZ TT GGGG UU
Portanto, ele pode encontrar as correspondências perfeitamente, mas não faz nada pelas linhas que não correspondem. Pode haver uma maneira de instruir sed
a exclusão dessas linhas; nesse caso, essa seria uma solução alternativa.