Como remover uma linha duplicada específica dentro de um arquivo?

3

Estou procurando uma maneira de remover uma linha específica de vários arquivos, mas somente se ocorrer mais de uma vez nesse arquivo. Outras linhas devem ser mantidas, mesmo que sejam duplicatas.

Por exemplo, um arquivo como este, no qual gostaria de remover as duplicatas de AAA

AAA
BBB
AAA
BBB
CCC

deve se tornar

AAA
BBB
BBB
CCC

Acho que devo usar sed , mas não tenho ideia de como escrever o comando.

    
por neXus 25.08.2017 / 17:39

3 respostas

7

Com o GNU sed :

sed '0,/^AAA$/b;//d'

Ou seja, deixe tudo ( b se ramificar como continue ) até o primeiro AAA (da 0ª linha (antes mesmo da primeira linha) e a primeira correspondendo /^AAA$/ (que pode ser a primeira linha)) e, em seguida, para as linhas restantes, exclua todas as ocorrências de AAA (um padrão // vazio reutiliza o último padrão).

O sed do GNU é necessário para o endereço 0 (e a capacidade de ter outros comandos após o b na mesma expressão, embora isso possa ser facilmente contornado em outras implementações usando dois -e expressões)

com awk :

awk '$0 != "AAA" || !n++'

(ou para um padrão de expressão regular: awk '!/^AAA$/ || !n++' )

uma abreviação de:

awk '! (&0 == "AAA" && count > 0) {print; count++}'
    
por 25.08.2017 / 17:55
2

awk solution de Stéphane Chazelas é lindo:

awk '!/AAA/ || !n++' file.in

Isso pode ser generalizado como

awk '$0 !~ pattern || !n++' pattern="$pattern" file.in

para uma determinada variável de shell $pattern contendo alguma expressão regular.

Se $pattern contiver barras invertidas, elas precisam ser escapadas ( \ ) ou você pode usar

P="$pattern" awk '$0 !~ ENVIRON["P"] || !n++' file.in
    
por 25.08.2017 / 18:04
0

Basta trocar os buffers cada vez que encontrar essa linha, se o espaço padrão contiver a mesma linha, exclua-a, ou recupere a linha do buffer de retenção:

sed -e '/^AAA$/{x;//d;g' -e'}' infile

ou

sed '/^AAA$/{
x
//d
g
}' infile
    
por 26.08.2017 / 01:00