Encontre ou extraia texto entre dois padrões na mesma linha ou em muitas linhas

1

Eu preciso imprimir o texto entre dois padrões sem ter em mente seu lugar, pois eles são encontrados aleatoriamente no arquivo. ou na mesma linha ou não na mesma linha ou um texto entre eles

Os padrões são: <abc> e </abc>

exemplo:

aslkdjas<abc>aaaa</abc><abc>bbbb</abc>sdkljasdl<abc>
cccc
dddd</abc>ieurwioeru<abc>eeee</abc>asdasd

Eu preciso de uma saída como a seguinte ou para ser separada por vírgulas do que acontecer nesse arquivo para exibir os valores entre dois padrões:

aaaa
bbbb
cccc
dddd
eeee
    
por Gebbo 27.10.2018 / 17:17

3 respostas

1

Eu não recomendo analisar qualquer código funcional com ferramentas de processamento de texto. Eles são simplesmente projetados para analisar apenas a linguagem humana e, mais cedo ou mais tarde, você ficará preso ao problema que não pode ser resolvido. Use ferramentas dedicadas (intérprete de html, compilador de c ++, etc.)

Com isso dito, neste caso, você pode tentar pcregrep :

pcregrep -Mo '<abc>\K(.|\n)*?(?=</abc>)' file

O resultado é

aaaa
bbbb

cccc
dddd
eeee

Sim, há uma nova linha entre bbbb e cccc porque no arquivo original temos nova linha. É claro que você pode canalizar a saída para remover espaços em branco se quiser (com tr , sed ou qualquer outro), mas como eu disse: nos exemplos da vida real você pode encontrar mais resultados inesperados.

    
por 27.10.2018 / 18:03
0

Para esse caso simples, tente

sed ':L1; N; $bL2; bL1; :L2; s#<abc>#^A#g; s#^[^^A]*^A##; s#</abc>[^^A]*^A#\n#g; s#</abc>.*$##; ' file
aaaa
bbbb

cccc
dddd
eeee

Colete todas as linhas no espaço padrão, substitua o padrão inicial por ^A , remova BOL do primeiro ^A , substitua as sequências entre os padrões com <new line> , remova o padrão até EOL, imprima.

    
por 28.10.2018 / 14:54
0

sed

Uma solução sed é converter os padrões e dois outros caracteres que não são usados dentro do arquivo em nenhum outro lugar. Isso converterá o problema no geral de extração entre dois caracteres únicos.

  1. Primeiro, converta cada padrão em caracteres únicos:

    sed 'H; $! d; x; s ## ^ A # g; s ## ^ B # g; ' arquivo

    Supondo que você tenha digitado Ctrl - V Ctrl - A para cada ^A e similarmente para ^B .

    O% inicial H;$!d;x; é capturar o arquivo inteiro no espaço padrão. Isso significa:

    • Mantenha todas as linhas
    • apaga o espaço do padrão (e retorna ao início) d
    • se for não a última linha $!
    • obtenha todas as linhas armazenadas no espaço de espera x . (pode ser g , mas x precisa de menos memória, pois o arquivo inteiro não é copiado do espaço de armazenamento para o espaço padrão).
  2. O processo geral para extrair um padrão entre dois caracteres únicos (suponha x e y aqui) é:

    sed 's # ^ [^ x] x ##; s # y [^ y] $ ##; s # y [^ x] * x #, # g; '

    Isto é:

    • remover os principais caracteres antes do primeiro ( ^ ) x .
    • remova os caracteres finais após o último ( $ ) y .
    • Converta caracteres entre y e x para um delimitador (vírgula ( , ) nesse caso).

Todos juntos:

$ sed 'H;$!d;x; s#<abc>#^A#g; s#</abc>#^B#g;' s#^[^^A]*^A##; s#^B[^^B]*$##; s#^B[^^A]*^A#,#g;' file
aaaa,bbbb,
cccc
dddd,eeee

grep

Isso pode ser feito com o (GNU) grep, mas ele precisa da ajuda de colar para colocar as vírgulas (apenas) nos lugares certos:

$ grep -ozP '(?s)<abc>\K.*?(?=</abc>)' file | paste -zsd ','; echo
aaaa,bbbb,
cccc
dddd,eeee
    
por 03.11.2018 / 06:43