Para remover linhas consecutivas que correspondam a um padrão e as próximas 3 linhas a seguir

0

Eu tenho um arquivo com o seguinte conteúdo:

dn : Does not matter
 uid=321 456 678
foo=/234
bar=/456
git=/543

 uid=321 456 678
 uid=678 987 098
foo=/234
bar=/456
git=/543

dn : Does it matter
 uid=321 456 678
foo=/543
bar=/423
git=/501

Eu quero remover quaisquer ocorrências de uid= que ocorram consecutivamente e também as 3 linhas seguintes para que a saída esperada seja:

 dn : Does not matter
 uid=321 456 678
foo=/234
bar=/456
git=/543

dn : Does it matter
 uid=321 456 678
foo=/543
bar=/423
git=/501

Eu tentei isso em dois servidores. Infelizmente, não tenho acesso ao servidor onde tentei a maior parte das minhas tentativas. Então, do segundo servidor, tentei variações dos seguintes, mas os resultados desejados estão me escapando.

sed '/^ uid=/N;{/\n uid= & & \n ^change type & & \n ^replace/d;}' pattern2.txt
awk '{/pat/?f++:f=0} f==2 {f--;}; 1' < pattern2.txt
sed '/^ uid=/N;{/\n uid=/D;}' pattern1.txt
awk '{/ uid=/?f++:f=0} f==2' pattern1.txt
    
por crusader 06.05.2018 / 17:07

2 respostas

0

Usando sed :

$ sed -f script.sed file
dn : Does not matter
 uid=321 456 678
foo=/234
bar=/456
git=/543

dn : Does it matter
 uid=321 456 678
foo=/543
bar=/423
git=/501

... onde script.sed é

H              # Append a newline and the current line to the hold space
/^$/bout       # Empty line: branch to ':out'
$bout          # Last line: branch to ':out'
d              # Delete line, start again from the top
:out
x              # Swap in the data from the hold space
/uid.*uid/d    # Delete the data if it contains two "uid"
s/\n//         # Remove the first embedded newline
               # (implicit print)

Isso coleta as linhas de leitura no "espaço de espera" (um buffer de uso geral em sed ) e quando atinge uma linha vazia ou o final da entrada, o espaço de espera contém um dos "blocos" no original Arquivo. Se tal bloco contiver duas instâncias da string uid , ele será descartado, caso contrário, será gerado.

    
por 06.05.2018 / 17:42
0

Com awk - acho que isso poderia ser simplificado, mas não foi possível até agora

awk '/uid=/ && p~/uid=/{c=4; next}
     !(c && c--) && NR>1{print p} {p=$0}
     END{if(c==0)print p}' ip.txt
  • por padrão, variáveis não inicializadas no awk serão string vazia ou 0 dependendo do contexto
  • /uid=/ && p~/uid=/ se a linha atual e a anterior contiverem uid=
    • c=4; next initialize c com o número de linhas a saltar (mais 1 por causa da lógica que acabei com). Além disso, pule o resto do código
  • !(c && c--) && NR>1{print p} imprime a linha anterior se o número da linha atual for maior que 1 e se c==0 . Se c for maior que 0 , continuará a decrementar até c==0
  • {p=$0} salve linha anterior para uso posterior
  • END{if(c==0)print p} imprime a última linha se c==0
por 06.05.2018 / 18:11