Acelere o grep e a gravação no arquivo
Eu apreciaria a ajuda de alguém. Atualmente, tenho 2 arquivos (ambos formatados da mesma forma) e ambos têm mais de 2 milhões de linhas em cada um. Exemplo de arquivos abaixo:
arquivo 1:
00000001 YYYY
00000002 NYNN
00000003 YNYN
...
...
arquivo 2:
00000001 YYNY
00000002 NYNN
00000003 YNYN
...
...
Portanto, observe que a primeira linha em cada arquivo é diferente, então eu imprimiria no arquivo 3:
00000001 YYYY
Para fazer o processo acima, tenho um script bash para:
- grep os primeiros OITO caracteres para o arquivo 2.
- Eu comparo o eco / saída do grep com a linha no arquivo 1.
- SE eles forem diferentes, escreva a linha (do arquivo 1) no arquivo 3.
Eu queria fornecer um código de amostra, mas lembre-se, acabei de inventar isso na hora, MAS é o mesmo conceito do meu script. Atualmente, estou 24 horas em e apenas na linha 240k de 2 milhões. Como posso acelerar isso de forma eficiente?
input="file1"
while IFS= read -r line
do
LineFromFile1=$("${echo $line}") firstEightChars=$("${echo $line:0:8}")
if grep -q "$firstEightChars" file2; then $LineFoundInFile2="$(grep $firstEightCharst file2)"
if [[ $line == $LineFoundInFile2 ]]; then
:
else
echo $line >> file3 done < "$input"
Respostas
Isso seria tão simples com um script Python.
Python tem a função zip que pode ser usada para ler e comparar dois arquivos linha por linha.
Exemplo de script Bash:
echo '00000001 YYYY
00000002 NYNN
00000003 YNYN' >file1
echo '00000001 YYNY
00000002 NYNN
00000003 YNYN' >file2
python3 -c '
with open("file1") as f_1, open("file2") as f_2:
for t in zip(f_1, f_2):
if t[0][8:-1] != t[1][8:-1]: print(t[0])'
Impressões:
00000001 YYYY
A vantagem aqui (sobre um awk
script simples, por exemplo) apenas uma linha de cada arquivo está na memória ativa - as duas linhas sendo comparadas.
No entanto, o Unix tem outras soluções para o problema descrito. Você também pode usar colar e awk
:
paste file1 file2 | awk '$2!=$4 {print $1 OFS $2}'
Ou se os números na primeira coluna estiverem agindo como um índice, você pode usar join e awk:
join file1 file2 | awk '$2!=$3 {print $1 OFS $2}'
Ou o comando comm (suprimindo a coluna 1 e a coluna 3) se a coluna 1 em cada arquivo for classificada também funcionará:
comm -1 -3 file1 file2
Todos os três comandos / canais Unix / Linux produzem:
00000001 YYYY