Remova duplicados de dois arquivos e mescle os únicos

1

Eu tenho dois grandes arquivos de texto, checksums_1.txt e checksums_2.txt, quero analisar esses arquivos e remover a duplicação entre eles e mesclar as linhas exclusivas em um arquivo.

Cada arquivo tem a seguinte estrutura para cada linha.

tamanho, md5, caminho

Exemplo: Checksums_1.txt

9565, a4fs614as6fas4fa4s46fsaf1, /mnt/app/1tier/2tier/filename.exe
9565, a4fs614as6fas4fa4s46fsaf1, /mnt/app/1tier/2tier/filename2.exe

Exemplo: Checksums_2.txt

9565, a4fs614as6fas4fa4s46fsaf1, /mnt/temp/1tier/2tier/filename.exe
9565, a4fs614as6fas4fa4s46fsaf1, /mnt/temp/1tier/2tier/filename2.exe
9565, a4fs614as6fas4fa4s46fsaf1, /mnt/temp/1tier/2tier/newfile.exe

A seção que deve ser usada para verificar entre checksums_1.txt e checksums_2.txt é após o ponto de montagem / mnt / app / e / mnt / temp /, ou seja, desde o início de cada linha até o final do ponto de montagem / mnt / temp / ou / mnt / app / será ignorado.

Os dados contidos no checksums_1.txt são mais importantes, por isso, se for encontrado um duplicado, a linha no checksums_1.txt deve ser movida para o arquivo mesclado.

Parte do Checksums_1.txt

1058,b8203a236b4f15316e516165a6546666,/mnt/app/Certificados/ca.crt
2694,8a815adefde4fa0c263e74832b15de64,/mnt/app/Certificados/ca.db.certs/01.pem
136,77bf2e5313dbaac4df76a4b72df2e2ad,/mnt/app/Certificados/ca.db.index

Parte do Checksums_2.txt

1058,b8203a236b4f1531616318284202c9e6,/mnt/temp/Certificados/ca.crt
3,72b2ac90f7f3ff075a937d6be8fc3dc3,/mnt/temp/Certificados/ca.db.serial 
2694,8a815adefde4fa0c263e74832b15de64,/mnt/temp/Certificados/ca.db.certs/01.pem
136,77bf2e5313dbaac4df76a4b72df2e2ad,/mnt/temp/Certificados/ca.db.index

Exemplo do arquivo mesclado

1058,b8203a236b4f15316e516165a6546666,/mnt/app/Certificados/ca.crt 
3,72b2ac90f7f3ff075a937d6be8fc3dc3,/mnt/temp/Certificados/ca.db.serial 
2694,8a815adefde4fa0c263e74832b15de64,/mnt/app/Certificados/ca.db.certs/01.pem
136,77bf2e5313dbaac4df76a4b72df2e2ad,/mnt/app/Certificados/ca.db.index
    
por André M. Faria 18.05.2015 / 23:11

3 respostas

1

Assumindo que ambos os arquivos não são enormes , o script python abaixo também fará o trabalho.

Como funciona

Ambos os arquivos são lidos pelo script. As linhas em file_1 (o arquivo que tem precedência) são divididas pelo diretório digitado para o arquivo na seção head (no seu exemplo /mnt/app/ ).

Posteriormente, as linhas no arquivo_1 são gravadas no arquivo de saída (o arquivo mesclado). Ao mesmo tempo, as linhas do arquivo_2 são removidas da lista de linhas se a cadeia de caracteres de identificação (a seção após o ponto de montagem) ocorrer na linha. Finalmente, as linhas "restantes" do arquivo_2 (das quais nenhum dupe existe no arquivo_1) são gravadas no arquivo de saída também. O resultado:

file_1:

1058,b8203a236b4f15316e516165a6546666,/mnt/app/Certificados/ca.crt
2694,8a815adefde4fa0c263e74832b15de64,/mnt/app/Certificados/ca.db.certs/01.pem
136,77bf2e5313dbaac4df76a4b72df2e2ad,/mnt/app/Certificados/ca.db.index

arquivo_2:

1058,b8203a236b4f15316e516165a6546666,/mnt/app/Certificados/ca.crt
3,72b2ac90f7f3ff075a937d6be8fc3dc3,/mnt/temp/Certificados/ca.db.serial
2694,8a815adefde4fa0c263e74832b15de64,/mnt/app/Certificados/ca.db.certs/01.pem
136,77bf2e5313dbaac4df76a4b72df2e2ad,/mnt/app/Certificados/ca.db.index

mesclado:

1058,b8203a236b4f15316e516165a6546666,/mnt/app/Certificados/ca.crt
2694,8a815adefde4fa0c263e74832b15de64,/mnt/app/Certificados/ca.db.certs/01.pem
136,77bf2e5313dbaac4df76a4b72df2e2ad,/mnt/app/Certificados/ca.db.index
3,72b2ac90f7f3ff075a937d6be8fc3dc3,/mnt/temp/Certificados/ca.db.serial

O script

#!/usr/bin/env python3
#---set the path to file1, file2 and the mountpoint used in file1 below
f1 = "/path/to/file_1"; m_point = "/mnt/app"; f2 = "/path/to/file_2"
merged = "/path/to/merged_file"
#---
lines1 = [(l, l.split(m_point)[-1]) for l in open(f1).read().splitlines()]
lines2 = [l for l in open(f2).read().splitlines()]

for l in lines1:
    open(merged, "a+").write(l[0]+"\n")
    for line in [line for line in lines2 if l[1] in line]:
            lines2.remove(line)

for l in lines2:
    open(merged, "a+").write(l+"\n")

Como usar

  1. Copie o script em um arquivo vazio, salve-o como merge.py
  2. na seção head do script, defina os caminhos para f1 ( file_1 ), f2 , o caminho para o arquivo de mesclagem e o ponto de montagem, conforme mencionado em file_1 .
  3. Execute-o pelo comando:

    python3 /path/to/merge.py
    

Editar

Ou um pouco mais curto:

#!/usr/bin/env python3
#---set the path to file1, file2 and the mountpoint used in file1 below
f1 = "/path/to/file_1"; m_point = "/mnt/app"; f2 = "/path/to/file_2"
merged = "/path/to/merged_file"
#---
lines = lambda f: [l for l in open(f).read().splitlines()]
lines1 = lines(f1); lines2 = lines(f2); checks = [l.split(m_point)[-1] for l in lines1]
for item in sum([[l for l in lines2 if c in l] for c in checks], []):
    lines2.remove(item)
for item in lines1+lines2:
    open(merged, "a+").write(item+"\n")
    
por Jacob Vlijm 19.05.2015 / 20:29
1

Se você estiver disposto a usar python (portanto, se o desempenho não for um problema), o que você deseja pode ser obtido com o seguinte script:

#!/usr/bin/env python3

import sys
import csv
import re

mountpoint1 = "/mnt/app/"
mountpoint2 = "/mnt/temp/"

if (len(sys.argv) != 4):
    print('Usage: {} <input file 1> <input file 2> <output file>'.format(sys.argv[0]))
    exit(1)

inputFileName1 = sys.argv[1]
inputFileName2 = sys.argv[2]
outputFileName = sys.argv[3]

# We place entries from both input files in the same dictionary
# The key will be the filename stripped of the mountpoint
# The value will be the whole line
fileDictionary = dict()

# First we read entries from file2, so that those
# from file2 will later overwrite them when needed
with open(inputFileName2) as inputFile2:
    csvReader = csv.reader(inputFile2)
    for row in csvReader:
        if len(row) == 3:
            # The key will be the filename stripped of the mountpoint
            key = re.sub(mountpoint2, '', row[2])
            # The value will be the whole line
            fileDictionary[key] = ','.join(row)

# Entries from file1 will overwrite those from file2
with open(inputFileName1) as inputFile1:
    csvReader = csv.reader(inputFile1)
    for row in csvReader:
        if len(row) == 3:
            # The key will be the filename stripped of the mountpoint
            key = re.sub(mountpoint1, '', row[2])
            # The value will be the whole line
            fileDictionary[key] = ','.join(row)

# Write all the entries to the output file
with open(outputFileName, 'w') as outputFile:
    for key in fileDictionary:
        outputFile.write(fileDictionary[key])
        outputFile.write('\n')

Basta salvar o script como merge-checksums.py , conceder permissão de execução

chmod u+x merge-checksums.py

e execute-o como:

./merge-checksums.py Checksums_1.txt Checksums_2.txt out.txt
    
por lgpasquale 19.05.2015 / 17:00
1

A versão bash (com awk e grep ):

#!/bin/bash

filename1=""
filename2=""

keys=$(awk -F'/' '{ for(i=4;i<NF;i++) printf "%s",$i "/"; if (NF) printf "%s",$NF; printf "\n"}' "$filename1" "$filename2" | awk '{gsub(/^[ \t]+|[ \t]+$/,"")};1' | sort -u)

while read -r key
do
    match=$(grep "$key" "$filename1")
    if [ "$match" != "" ]
    then
        echo "$match"
    else
        grep "$key" "$filename2"
    fi
done <<< "$keys"

Checksums_1.txt

9565, 1111111111111111111111111, /mnt/app/1tier/2tier/filename.exe
9565, 0000000000000000000000000, /mnt/app/1tier/2tier/filename2.exe

Checksums_2.txt

9565, 2222222222222222222222222, /mnt/temp/1tier/2tier/filename.exe
9565, 0000000000000000000000000, /mnt/temp/1tier/2tier/filename2.exe
9565, 3333333333333333333333333, /mnt/temp/1tier/2tier/newfile.exe

Executar com

./merge_checksum Checksums_1.txt Checksums_2.txt > Checksums_3.txt

Checksums_3.txt

9565, 1111111111111111111111111, /mnt/app/1tier/2tier/filename.exe
9565, 0000000000000000000000000, /mnt/app/1tier/2tier/filename2.exe
9565, 3333333333333333333333333, /mnt/temp/1tier/2tier/newfile.exe

Ou com arquivos de entrada intercambiados

./merge_checksum Checksums_2.txt Checksums_1.txt > Checksums_3.txt

Checksums_3.txt

9565, 0000000000000000000000000, /mnt/temp/1tier/2tier/filename2.exe
9565, 2222222222222222222222222, /mnt/temp/1tier/2tier/filename.exe
9565, 3333333333333333333333333, /mnt/temp/1tier/2tier/newfile.exe
    
por A.B. 19.05.2015 / 17:47