Temos o seguinte arquivo de texto:
172.55.34.48 172.55.33.95
172.55.32.163 172.55.34.48
172.55.32.163 172.55.33.95
O que precisamos fazer é trocar as duas colunas se a primeira coluna for encontrada contendo um valor já encontrado anteriormente naquela coluna. Para cada valor desse tipo (endereços IP neste caso), a ocorrência máxima é dois.
No exemplo acima, precisamos trocar 172.55.33.95
com 172.55.32.163
o que 172.55.32.163
já foi encontrado na linha anterior.
tentei
awk 'prev && ($1 != prev) {print seen[prev]} {seen[$1] = $0; prev = $1} END {print seen[$1]}' /tmp/new.txt
mas isso ajuda a remover linhas onde a entrada da coluna 1 já foi encontrada antes.
A resposta pode ser tão simples quanto este programa awk:
Isso armazenará a contagem de ocorrências de cada valor da coluna 1 em uma matriz
found
aumentando o valor da matriz correspondente. Se o valor for maior que um, isso significa que o valor atual já foi encontrado e as colunas precisam ser trocadas.Para fazer isso, o valor da coluna 1 é armazenado em um buffer, substituído pelo valor da coluna 2, e o valor da coluna 2 por sua vez pelo valor armazenado em buffer. No final, a linha atual é impressa incluindo todas as modificações (se houver), que é o significado do aparentemente "disperso"
1
.Essa abordagem simples tem uma desvantagem: se o novo valor da coluna 1 (anteriormente coluna 2) ocorrer na coluna 1 novamente em uma linha posterior ou já tiver ocorrido em uma linha anterior, isso não será capturado. Uma versão melhorada, que considera a ocorrência em linhas posteriores e omite linhas onde a troca também produziria uma entrada duplicada da coluna 1, poderia ter a seguinte aparência:
Em Perl você pode fazer:
-l
: remove e adiciona automaticamente o separador de campo de registro padrão (\n
) antes e depois de cada avaliação do script passado para-e
;-a
: divide automaticamente cada linha no separador de campo de entrada padrão (O script definirá o separador de campo de saída como
, então, para cada linha, ele verificará se o primeiro campo já está armazenado em
@buf
.Se for, ele reverterá o registro atual e o imprimirá; caso contrário, ele imprimirá o registro atual e adicionará o primeiro campo a
@buf
.Seus requisitos não são claros e seu exemplo não cobre todas as possibilidades do que você pode querer dizer, mas, usando qualquer awk, isso implementará uma coisa que você pode querer dizer:
ou talvez você queira:
ou:
ou: