2010-11-13 8 views
1

J'ai besoin d'un script pour éditer les fichiers. Je deviens un peu fou à ce sujet déjà :).Comparaison de deux fichiers en utilisant le script bash

J'ai deux fichiers:

143956;lorem 
143957;ipsum 
143958;lala 
143959;vuvu 

et deuxième

512;143956;15 
2156;143957;15 
153;143958;4968 
2156;143959;486 

Et ce que je besoin est de mettre ces deux fichiers ensemble de cette façon:

512;143956;lorem;15 
2156;143957;ipsum;15 
153;143958;lala;4968 
2156;143959;vuvu;486 

Ce ne semble pas si difficile et probablement paste serait suffisant, mais theres un attrapé. Il y a des lignes qui sont seulement dans un de ces fichiers mais ne sont pas dans l'autre. Dans ce cas, je dois attendre sur la ligne sur le deuxième fichier et toujours en comparant à la première.

Exemple:

143956;lorem 
143957;ipsum 
143959;vuvu //here "lulu" is missing, will compare with 3rd line (143958) but the script wont declare this as "not found" but keep on searching till finds 143959 (which is already on 4 in this case). 

512;143956;15 
2156;143957;15 
153;143958;4968 
2156;143959;486 

La sortie ressemblerait à ceci alors:

512;143956;lorem;15 
2156;143957;ipsum;15 
2156;143959;vuvu;486 

Ou mieux cette façon

512;143956;lorem;15 
2156;143957;ipsum;15 
153;143958;*WAS NOT FOUND*;4968 
2156;143959;vuvu;486 

Mais je peux terminer que moi-même ...

J'espère que c'est compréhensible. Merci beaucoup pour toute aide.

+0

Merci d'envoyer votre entrée incluant par exemple un cas limite. Pourriez-vous également publier la sortie attendue pour ce cas? –

+0

Faut-il être dans 'bash' ou pourrions-nous passer à un langage de programmation approprié comme python? –

+0

Merci pour la réponse Mark, j'ai édité la question en incluant la sortie de cas de bord. – tsusanka

Répondre

1

Utiliser la substitution de processus Bash (<()) et l'join utilité:

join -t \; -1 1 -2 2 -o 2.1,2.2,1.2,2.3 <(sort file1) <(sort -t \; -k2,2 file2) 

Vous pouvez également trier les fichiers.

Pour sortir les enregistrements qui apparaissent dans fichier2 mais ne figurent pas dans fichier1:

join -t \; -1 1 -2 2 -v 2 -o 2.1,2.2,1.2,2.3 <(sort file1) <(sort -t \; -k2,2 file2) | sed 's/;;/;*WAS NOT FOUND*;/' 
+0

Super, on dirait que ça marche! Je vais l'essayer pleinement demain - j'ai besoin de dormir maintenant. Mais ça a l'air vraiment génial. Merci – tsusanka

+0

oui cela fonctionne! merci beaucoup – tsusanka

+0

Theres juste un pense que je reçois double \ n là-bas, parce que nous utilisons les parties finales dans les deux fichiers, puis-je me débarrasser de cela? – tsusanka

1

Si le premier fichier est pas trop grand, vous pouvez le faire (test1 et test2 sont deux fichiers dans l'ordre que vous avez spécifié):

#!/bin/sh 

for line in `cat test2`; do 
    number=`echo "$line" | grep -o ";[0-9]*;" | sed 's/;//g'` 
    repl=`grep "$number;" test1` 
    if [ -z "$repl" ]; then 
    echo "$line" | sed "s#;$number;#;$number;*WAS NOT FOUND*;#g" 
    else 
    echo "$line" | sed "s#;$number;#;$repl;#g" 
    fi 
done 
+0

Malheureusement c'est - environ 30 Mb. J'obtiens cette erreur "./sc: 11: sed: La liste d'arguments est trop longue" quand j'ai trié les fichiers. Avant quand je n'ai pas eu de résultats, mais il a écrit un message différent - je peux l'écrire ici mais le tri est la bonne chose de toute façon, ou n'est-ce pas? – tsusanka

+0

Bien que les données de la question ne contiennent aucun espace, c'est une mauvaise habitude d'utiliser 'for $ (cat file)' car cela va casser chaque mot sur une ligne distincte. La façon correcte de le faire est 'while while read -r line; fais ... fait