Procura por uma string e imprime tudo antes e depois dentro de um intervalo

9

Eu tenho este arquivo:

sometext1{
string1
}

sometext2{
string2
string3
}

sometext3{
string4
string5
string6
}

Eu quero pesquisar este arquivo para uma string específica e imprimir tudo antes desta string até a abertura { e tudo depois dessa string até o fechamento } . Eu tentei conseguir isso com sed mas se eu tentar imprimir tudo no intervalo /{/,/string2/ por exemplo sed imprime isso:

sometext1{
string1
}

sometext2{
string2
sometext3{
string4
string5
string6
}

Se eu procurar pela string "string2", preciso que a saída seja:

sometext2{
string2
string3
}

Obrigado.

    
por rodrigo 19.12.2014 / 14:14

5 respostas

9

Aqui estão dois comandos. Se você quiser um comando que apareça até a última linha .*{$ em uma sequência (como @don_crissti com ed ) você pode fazer:

sed 'H;/{$/h;/^}/x;/{\n.*PATTERN/!d'

... que funciona anexando todas as linhas ao espaço H old após um caractere \n ewline, sobrescrevendo h old space para cada linha que corresponda a {$ e trocando h old por pattern espaços para cada linha que corresponda a ^} - e, portanto, liberando seu buffer.

Ele imprime apenas linhas que correspondem a { e, em seguida, \n ewline e, em seguida, PATTERN - e isso só acontece imediatamente após uma troca de buffer.

Ele elimina todas as linhas em uma série de {$ corresponde ao último da sequência, mas você pode obter todas essas inclusões como:

sed '/PATTERN.*\n/p;//g;/{$/,/^}/H;//x;D'

O que ele faz é padrão de troca e h espaços antigos para cada sequência de ...{$.*^}.* , anexa todas as linhas da sequência ao espaço H old após um caractere \n ewline e D elips até o primeiro caractere% e_line \n no espaço padrão para cada ciclo de linha antes de iniciar novamente com o que permanece.

Naturalmente, a única vez em que ele recebe \n ewline no espaço padrão é quando uma linha de entrada corresponde a ^} - o fim de seu intervalo - e quando ele executa novamente o script em qualquer outra ocasião a próxima linha de entrada por costume.

Quando PATTERN é encontrado no mesmo espaço de padrão que um \n ewline, ele imprime o lote antes de sobrescrevê-lo com ^} novamente (para que possa finalizar o intervalo e liberar o buffer) .

Dado este arquivo de entrada (obrigado don) :

sometext1{
string1
}

sometext2{
PATTERN
string3
}

sometext3{
string4
string5
string6
}

Header{
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}
}

As primeiras impressões:

sometext2{
PATTERN
string3
}
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}

... e o segundo ...

sometext2{
PATTERN
string3
}
Header{
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}
    
por 19.12.2014 / 14:59
6

Aqui está uma solução com ed :

ed -s filename <<< $'g/PATTERN/?{?,/}/p\nq\n'

isto é:

g/PATTERN/     # mark each line matching PATTERN  
?{?,/}/p       # for each marked line, print all lines from the previous { up to the next }  
q              # quit editor

Isso pressupõe que exista apenas uma linha com PATTERN entre cada par de { } , caso contrário você obterá saída duplicada para cada linha adicional com PATTERN dentro do mesmo bloco.
Ele funcionará para vários { } contendo uma única linha correspondente a PATTERN , por exemplo, para um arquivo de teste com PATTERN em duas seções diferentes:

sometext1{
string1
}

sometext2{
PATTERN
string3
}

sometext3{
string4
string5
string6
}

Header{
sometext4{
some string

string unknown

here's PATTERN again

another string here
}
}

executando

ed -s sample <<< $'g/PATTERN/?{?,/}/p\nq\n'

saídas:

sometext2{
PATTERN
string3
}
sometext4{
some string

string unknown

here's PATTERN again

another string here
}
    
por 19.12.2014 / 15:30
4

com pcregrep :

pcregrep -M '(?s)\{[^}]*PATTERN.*?\}'

Ou com o GNU grep , desde que a entrada não contenha bytes NUL:

grep -Poz '.*(?s)\{[^}]*PATTERN.*?\}'
    
por 21.04.2016 / 11:52
0
$ awk 'BEGIN{RS="\n\n"; FS="[{}]"} {if ($2 ~ /string4/) {print $2}}' t1.txt
string4
string5
string6

onde:

  • string4 - > string a ser correspondida
  • t1.txt - > contém o conteúdo do arquivo mencionado na consulta
por 18.01.2017 / 17:17
-2

sed -n '/ string / p' nome do arquivo

o -n quando adicionado ao sed suprimiu o comportamento padrão do sed, esta declaração pode não lhe dar exatamente o que você quer, mas deve apenas deslocar a string, espero que isso tenha ajudado

    
por 19.12.2014 / 14:39