como extrair uma parte do texto de um arquivo entre condições correspondentes

como extrair uma parte do texto de um arquivo entre condições correspondentes

Eu tenho um arquivo como abaixo.

~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

~PAR2~
This is Par2 line 1
This is Par2 line 2

Par Finished

Se eu passar PAR1, devo obter todas as linhas entre PAR1e Par Finishedlinha. Como posso conseguir? Estava pesquisando awke sednão encontrei nenhuma opção.

Responder1

Se você quiser a linha de cabeçalho e rodapé, é bem simples, por sed exemplo

sed -n "/^~PAR1~$/,/Par Finished/p"

Isso é simples de usar com uma variável

START=PAR1
sed -n "/^~$START~$/,/Par Finished/p"

Também podemos fazer com que a última linha seja uma variável

START=PAR1
END="Par Finished"
sed -n "/^~$START~$/,/$END/p"

O resultado é semelhante a:

~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

Agora, se você não quer as linhas de início/fim e não quer a linha em branco, então é um pouco mais complicado.

Pode haver maneiras melhores, mas isso funciona para mim:

sed -n "/^~$START~$/,/$END/ { /^~$START~$/d ; /$END/d ; /^$/d ; p }"

O resultado disso é

This is Par1 line 1
This is Par1 line 2

Responder2

Você pode usar a Par Finishedlinha (com linhas em branco opcionais) como separador de registros (e substituí-la para completar o registro)

awk -vRS='\nPar Finished\n*' -vp='PAR1' '$0 ~ p {print $0,"\nPar Finished"}' parfile
~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

Se você tiver GNUo awk, poderá recuperar o separador de registros com a variável especial RT(removendo as novas linhas extras, se desejar)

gawk -vRS='\nPar Finished\n*' -vp='PAR1' '$0 ~ p {sub("\n*$", "", RT); print $0,RT}' parfile
~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

Claro que se você não precisa passar por umvariável Par1você usa um intervalo de regex simples

awk '/PAR1/,/Par Finished/' parfile
~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

Responder3

Com grepe pcrepara entrada de arquivo suficientemente pequena

$ s="PAR1"

$ grep -oPz "(?s)[^\n]*${s}.*?\n.*?Par Finished.*?\n" ip.txt 
~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

Para obter linhas entre o padrão:

$ grep -oPz "(?s)${s}.*?\n\K.*?(?=Par finalizado)" ip.txt
Esta é a linha 1 do Par1
Esta é a linha 2 do Par1

Alterando variável paraPAR2

$s="PAR2"
$ grep -oPz "(?s)${s}.*?\n\K.*?(?=Par finalizado)" ip.txt
Esta é a linha Par2 1
Esta é a linha Par2 2

Referência: Regex (grep) para pesquisa multilinha

informação relacionada