Encontre cada linha que corresponda a um padrão, mas imprima apenas a linha acima dela

4

Eu preciso encontrar uma string e preciso imprimir a linha acima dela.

case1: The same line won't have the more than one matching pattern

ie) considere um arquivo contendo

$cat > para
returns between the paragaraphs
italic or bold    
quotes by placing
italic

Aqui eu preciso encontrar o itálico, e preciso obter a saída como abaixo

returns between the paragaraphs
quotes by placing

Como posso obter o resultado assim?

    
por jevan 20.02.2016 / 02:44

2 respostas

5

Se o padrão não puder ocorrer em linhas consecutivas, você pode simplesmente executar

sed '$!N;/.*\n.*PATTERN.*/P;D' infile

Eu expliquei aqui como funciona o ciclo N ; P ; D . A diferença é que aqui a primeira linha no espaço padrão é impressa apenas se a segunda for igual, caso contrário, ela será excluída.

Se o padrão puder ocorrer em linhas consecutivas, a solução acima imprimirá uma linha que corresponda se for seguida por outra linha que corresponda.
Para ignorar correspondências consecutivas, adicione uma segunda condição para imprimir a primeira linha no espaço padrão apenas se não corresponder:

sed '$!N;/.*\n.*PATTERN.*/{/.*PATTERN.*\n.*/!P;};D' infile

Outra maneira, usando o buffer de espera.
Se você quiser ignorar correspondências consecutivas:

sed '/PATTERN/!{              # if line doesn't match PATTERN
h                             # copy pattern space content over the hold buffer
d                             # delete pattern space
}
//{                           # if line matches PATTERN
x                             # exchange pattern space with hold space
//d                           # if line matches PATTERN delete it
}' infile

ou, em uma linha

sed '/PATTERN/!{h;d;};//{x;//d;}' infile

Se você não quiser ignorar correspondências consecutivas:

sed '/PATTERN/!{              # if line doesn't match PATTERN
h                             # copy pattern space content over the hold buffer
d                             # delete pattern space
}
//x                           # if line matches PATTERN exchange buffers
' infile 

ou, em uma linha

sed '/PATTERN/!{h;d;};//x' infile

Embora tenha em mente que as soluções que usam o buffer de retenção imprimirão uma linha vazia principal se a primeira linha do arquivo corresponder.

    
por 20.02.2016 / 03:41
2

Usando o grep , então sed :

grep --no-group-separator -B 1 "italic" <yourfilename> | sed -n 1~2p'

Explicação:

Manual do

grep :

-B num
--before-context=num
Print num lines of leading context before matching lines

--no-group-separator
When -A, -B or -C are in use, do not print a separator between groups of lines.

sed :

Escolha a primeira linha de dois. Poderíamos também colocar sed -n 1 ~ 5p para escolher o primeiro dos cinco.

    
por 20.02.2016 / 03:28