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

4

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 PAR1 e Par Finished line. Como posso conseguir? Eu estava pesquisando awk e sed e não encontrei nenhuma opção.

    
por Adriana 24.09.2016 / 15:10

3 respostas

8

Se você quer a linha de cabeçalho e rodapé, é bem simples com sed eg

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 tornar a última linha uma variável

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

O resultado parece:

~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, é 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
    
por 24.09.2016 / 16:20
2

Você pode usar a linha Par Finished (com linhas em branco finais opcionais) como separador de registro (e, em seguida, substituí-la para concluir 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ê tem GNU awk, você pode recuperar o separador de registro 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 precisar passar uma variável Par1 , use um intervalo de regex simples

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

Par Finished
    
por 24.09.2016 / 16:01
2

Com grep e pcre para entrada de arquivo pequena o suficiente

$ 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 Finished)" ip.txt 
This is Par1 line 1
This is Par1 line 2

Alterando a variável para PAR2

$ s="PAR2"
$ grep -oPz "(?s)${s}.*?\n\K.*?(?=Par Finished)" ip.txt 
This is Par2 line 1
This is Par2 line 2

Referência: Regex (grep) para multi pesquisa de linha

    
por 24.09.2016 / 17:59