Como encontrar linhas exclusivas de cada arquivo com 3 arquivos de texto

Como encontrar linhas exclusivas de cada arquivo com 3 arquivos de texto

Tenho três arquivos de texto com alguns IDs exclusivos e quero manter apenas IDs exclusivos em cada arquivo de texto. Digamos que existam 3 arquivos (A, B e C). Se um ID "abc" aparecer em A e B, ele precisará ser removido de ambos os arquivos.

Os arquivos são classificados e têm menos de 1 MB de tamanho e os IDs são caracteres alfanuméricos. Também dentro de cada arquivo, não há duplicatas.

Existe uma maneira de fazer isso usando ferramentas de linha de comando no Linux ou Mac? Eu estava pensando em escrever um código inicialmente, mas queria perguntar primeiro. Obrigado!

Responder1

Premissas:

  • os arquivos de texto possuem um único ID por linha
  • cada linha contém apenas um ID e nenhum outro texto
  • os IDs não são repetidos dentro de um arquivo
  • não há problema em reordenar o arquivo de saída (classificá-lo)
  • eficiência de execução não é importante
  • Os IDs são alfanuméricos
$ cat A B B C C | sort | uniq -u >A.uniq
$ cat B A A C C | sort | uniq -u >B.uniq
$ cat C A A B B | sort | uniq -u >C.uniq
$ mv A.uniq A
$ mv B.uniq B
$ mv C.uniq C

O comando 'cat' concatena os arquivos listados. O primeiro arquivo é aquele que desejo eliminar as duplicatas. Os próximos arquivos são as possíveis duplicatas que desejo eliminar. Eu adiciono duas cópias de cada um desses arquivos para garantir que eles sejam duplicados e serão removidos.

Em seguida, eu “classifico” esses arquivos em ordem alfabética. Isso resulta em quaisquer IDs duplicados em linhas vizinhas na saída classificada.

O comando 'uniq' com a opção '-u' gera apenas linhas que são uniq. Se dois ou mais IDs iguais aparecerem em linhas vizinhas na entrada, nada será gerado.

O '>' grava a saída em um novo arquivo chamado 'A.uniq'

Se você quisesse fazer o oposto e gerar uma lista de todos os IDs que estão duplicados nos 3 arquivos, você poderia fazer algo como:

$ cat A B C | sort | uniq -d >duplicates

O comando 'uniq' com o sinalizador '-d' só gera uma linha se for repetida duas ou mais vezes na entrada.

Responder2

Obrigado pela distração - criei o seguinte script (documentado) -

#! /bin/bash

SOURCEFILES="./existing/list1.txt  ./existing/list2.txt  ./existing/list3.txt"

# First find a list of duplicate files.  We do this by catting all files and finding where there are lines that are not unique

# $DUPLICATES will be a space seperated list of duplicate IDs

DUPLICATES=$( cat $SOURCEFILES | sort | uniq -d )
echo "Duplicates Found for removal: " $DUPLICATES

# Convert list of duplicates into a pipe seperated list
# Commented out version assumes all ID's are all the same length, so it would break if one is ABC and another is ABCD 
#DUPLICATES=$( echo $DUPLICATES | tr ' ' '|' )

# This version translates the duplicate REGEX to say that each line is complete 
# ^ means start of line and $ means end of line.

for each in $DUPLICATES
do
    DUPLIST="$DUPLIST^$each$|"
done

# Remove trailing "|" from DUPLIST
DUPLICATES=$( echo ${DUPLIST::-1} )


# Go through each file, removing duplicates 
for each in $SOURCEFILES
do
    mv $each $each.old
    egrep -v "$DUPLICATES" < $each.old > $each
done

informação relacionada