Remova linhas duplicadas adjacentes enquanto mantém a ordem

11

Eu tenho um arquivo com uma coluna com nomes que se repetem várias vezes cada. Quero condensar cada repetição em uma, mantendo outras repetições com o mesmo nome que não sejam adjacentes a outras repetições com o mesmo nome.

Por exemplo, eu quero virar o lado esquerdo para o lado direito:

Golgb1    Golgb1    
Golgb1    Akna
Golgb1    Spata20
Golgb1    Golgb1
Golgb1    Akna
Akna
Akna
Akna
Spata20
Spata20
Spata20
Golgb1
Golgb1
Golgb1
Akna
Akna
Akna

Isto é o que eu tenho usado: perl -ne 'print if ++$k{$_}==1' file.txt > file2.txt No entanto, esse método mantém apenas um representante da esquerda (ou seja, Golb1 e Akna não são repetidos).

Existe uma maneira de manter nomes exclusivos para cada bloco, mantendo nomes que se repetem em vários blocos não adjacentes?

Idade87
fonte

Respostas:

23

uniq fará isso por você:

$ uniq inputfile
Golgb1
Akna
Spata20
Golgb1
Akna
DopeGhoti
fonte
2
uau, isso foi embaraçosamente fácil! obrigado!
precisa saber é o seguinte
@ O Age87 Unix é ótimo! Isso funciona apenas porque você espera que as duplicatas já sejam adjacentes (ou não desejam remover as não adjacentes). Normalmente, a recomendação é usarsort | uniq
jpaugh 23/04
1
Ou de forma mais sucinta, sort -u(:
DopeGhoti
9

Awk solução:

awk '$1 != name{ print }{ name = $1 }' file.txt

A saída:

Golgb1
Akna
Spata20
Golgb1
Akna
RomanPerekhrest
fonte
6

Tente isso - salve a linha anterior e compare com a linha atual

$ perl -ne 'print if $p ne $_; $p=$_' ip.txt
Golgb1
Akna
Spata20
Golgb1
Akna

Você marcou uniqtambém - você experimentou?

$ uniq ip.txt
Golgb1
Akna
Spata20
Golgb1
Akna
Sundeep
fonte
1

Com o sed, isso pode ser feito da seguinte maneira:

sed -e '$!N;/^\(.*\)\n\1$/!P;D' input_file

Aqui temos no espaço do padrão a qualquer momento 2 linhas. Quando a comparação falha, imprimimos o primeiro e cortamos de frente, voltamos e acrescentamos a próxima linha ao espaço do padrão. Enxágüe ... repita

Utilizando Perl no modo slurp, tratamos o arquivo inteiro como uma sequência longa na qual o regex é aplicado, o que faz a comparação para você.

perl -0777pe 's//$1/ while /^(.*\n)\1+/gm' input_file
Rakesh Sharma
fonte
0

Pergunta sobre a solução sed de Rakesh Sharma.

E se você tiver um arquivo de entrada como:

-126.1 48.206
-126.106 48.21
-126.11 48.212
-126.114 48.214
-126.116 48.216
-126.118 48.216
-126.128 48.222
-126.136 48.226

E você deseja que um arquivo de saída seja:

-126.1 48.206
-126.106 48.21
-126.11 48.212
-126.114 48.214
-126.116 48.216
-126.128 48.222
-126.136 48.226

Observe a falta:

-126.118 48.216

Eu sei que o comando que eu quero é semelhante à sua solução:

sed -e '$!N;/^\(.*\)\n\1$/!P;D' input_file

Não é possível alterá-lo da maneira correta para imprimir as duas colunas e apenas ser classificado dessa maneira especial com os valores da coluna 2. Alguma dica?

MattS
fonte
sed -e '$!N' -e '/.*\.\([0-9]*\)\n.*\.\1$/!{P;D;}' -e 's/\n.*//;s/^/\n/;D' excluirá os elementos repetidos subsequentes. Nota: Isso requer GNU sed. Para o POSIXcomportamento, ele precisa de uma ligeira alteração.
Rakesh Sharma