Accélérer grep et écrire dans un fichier
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:
- grep les HUIT premiers caractères du fichier 2.
- Je compare l'écho / la sortie du grep avec la ligne du fichier 1.
- 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
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 awk
script 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