Accélérer grep et écrire dans un fichier

Aug 18 2020

J'apprécierais l'aide de n'importe qui. Actuellement, j'ai 2 fichiers (tous deux formatés de la même manière) et ils ont tous les deux plus de 2 millions de lignes dans chacun. Exemple de fichiers ci-dessous:

fichier 1:

00000001 YYYY
00000002 NYNN
00000003 YNYN
...
...

fichier 2:

00000001 YYNY
00000002 NYNN
00000003 YNYN
...
...

Notez donc que la première ligne de chaque fichier est différente, je voudrais donc imprimer dans le fichier 3:

00000001 YYYY

Pour effectuer le processus ci-dessus, j'ai un script bash pour:

  1. grep les HUIT premiers caractères du fichier 2.
  2. Je compare l'écho / la sortie du grep avec la ligne du fichier 1.
  3. S'ils sont différents, écrivez la ligne (du fichier 1) au fichier 3.

Je voulais fournir un exemple de code, mais gardez à l'esprit que je viens de l'inventer à la volée MAIS c'est le même concept que mon script. Actuellement, je suis 24 heures sur 24 et seulement en ligne 240k sur 2 millions. Comment puis-je accélérer cela de manière efficace?

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"

Réponses

5 dawg Aug 18 2020 at 11:06

Ce serait si simple avec un script Python.

Python a la fonction zip qui peut être utilisée pour lire et comparer deux fichiers ligne par ligne.

Exemple 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])'

Impressions:

00000001 YYYY

L'avantage ici (par rapport à un simple awkscript par exemple), une seule ligne de chaque fichier est en mémoire active - les deux lignes étant comparées.

Cependant, Unix a d'autres solutions au problème décrit. Vous pouvez également utiliser coller et awk:

paste file1 file2 | awk '$2!=$4 {print $1 OFS $2}'

Ou si les nombres de la première colonne agissent comme un index, vous pouvez utiliser join et awk:

join file1 file2 | awk '$2!=$3 {print $1 OFS $2}'

Ou la commande comm (en supprimant col 1 et col 3) si la colonne 1 de chaque fichier est triée fonctionnera également:

comm -1 -3 file1 file2

Les trois commandes / tubes Unix / Linux produisent:

00000001 YYYY