Eu tenho um arquivo onde as strings são separadas por uma string especial (não uma vírgula ou delimitador), por exemplo <vvv>
. Eu quero verificar se todas as strings no primeiro campo são únicas. Se forem encontradas linhas duplicadas para o mesmo campo, desejo remover todas as linhas repetidas (deixe a primeira ocorrência).
Exemplo:
aaa<vvv>bbb<vvv>ccc
xxx<vvv>yyy<vvv>zzz
aaa<vvv>new<vvv>new2
111<vvv>222<vvv>333
Eu quero obter:
aaa<vvv>bbb<vvv>ccc
xxx<vvv>yyy<vvv>zzz
111<vvv>222<vvv>333
Removemos aaa<vvv>new<vvv>new2
porque aaa
já apareceu.
Eu não prefiro a nós , a awk
menos que seja a única solução. Sua sintaxe é um pouco complexa para mim como um desconhecido para o Linux.
Sem usar
awk
muito :Isso só serve
awk
para inserir um número de linha seguido de<
nos dados originais. Fazemos isso para poder acompanhar a ordenação das linhas originais. Usamos<
como delimitador entre o número da linha e o resto da linha porque este também aparece como delimitador entre o primeiro campo original e o resto da linha.Após o primeiro estágio do pipeline, no qual
awk
é usado para inserir os números das linhas, os dados ficarão comoA próxima etapa do pipeline classifica isso no segundo campo (o primeiro campo original), removendo duplicatas. O resultado será
O segundo
sort
restaura a ordem de linha original ordenando as linhas no primeiro campo numericamente, e obtemosO
cut
então remove os números do primeiro campo (e o delimitador inserido).Uma solução que fornece saída ordenada sem usar
awk
nada pareceriaEsta é essencialmente a segunda etapa no pipeline acima e classifica o arquivo no primeiro campo enquanto remove duplicatas.
Uma
awk
solução seria comoIsso armazena o primeiro campo como uma chave em uma matriz associativa chamada
seen
e pós-incrementa o valor associado. Se o valor na matriz para a chave fornecida for zero (ou seja, este primeiro campo não foi visto antes), a linha é impressa.Ou equivalentemente com nem
awk
nemcut
, mas comsed
:Mas isso é muito chato. A última solução do @Kusalananda (baseada em awk) é muito melhor.
Apenas por uma questão de pedagogia, os dois primeiros
sed
blocos acima, são equivalentes ao cmd mais compacto de Kusalanandaawk
:sed '=' file
, imprime números de linha para pedidos futurossed 'N;s/\n/</'
, acrescenta a próxima linha de entrada no espaço do padrão (ou seja, "junta as linhas atual e seguinte") e substitui o final da linha\n
por<
.A 3ª e última
sed
dica,sed 's/^[0-9]*<//'
, substitui o número da linha e o "<" colocado no início de cada linha, sem nada.Para obter mais detalhes sobre o
sed
problema,$ info sed
em seu console.Usando GNU sed, podemos fazer a tarefa como dada:
Armazene o primeiro campo no espaço de espera e compare-o com o primeiro campo da linha atual. Somente quando forem diferentes, atualize a espera como também imprima a linha atual.
Tentei com abaixo de 2 métodos
resultado