2009-01-18 6 views
70

J'essaie de trouver un moyen de déterminer la différence entre deux chaînes dans mon script. Je pourrais facilement le faire avec diff ou comm, mais je ne traite pas des fichiers et je préférerais ne pas les sortir en fichiers, faire la comparaison et le relire.Différence de chaînes Bash

Je vois que comm, diff, cmp tous permettent de passer soit deux fichiers OU un fichier et une entrée standard - je suppose que c'est bon si je ne veux pas sortir deux fichiers ... mais il est encore un peu suce. En train de fouiller en pensant que je peux utiliser grep ou des expressions régulières - mais je suppose que non.

Merci à l'avance,

+1

qu'est-ce que vous voulez vraiment faire? – hop

+0

Vous pouvez utiliser les manipulations de sous-chaîne et les opérations de test intégrées avec les changements IFS pour comparer, mais vous devez savoir si vous voulez comparer caractère par caractère, mot par mot, ligne par ligne, ignorer les espaces blancs ... – technosaurus

+0

Voir https://stackoverflow.com/questions/34376884/highlight-string-differences – mosh

Répondre

9

me rappelle cette question: How can you diff two pipelines in Bash?

Si vous êtes dans une session bash, vous pourriez faire:

diff <cmd1 <cmd2 
diff <(foo | bar) <(baz | quux) 

avec < créer des tuyaux anonymes nommés - - géré par bash - donc ils sont créés et détruits automatiquement, contrairement aux fichiers temporaires.

Donc, si vous parvenez à isoler vos deux chaînes différentes dans le cadre d'une commande (grep, awk, sed, ...), vous pouvez le faire - par exemple - quelque chose comme:

diff < grep string1 myFile < grep string2 myFile 

(si vous supposons que vous avez dans vos lignes de fichiers comme string1=very_complicated_value et string2=another_long_and_complicated_value': sans connaître le format interne de votre dossier, je ne peux pas recommander une commande précise)

124

en utilisant diff ou com ou tout ce que vous voulez:

diff <(echo "$string1") <(echo "$string2") 

Bash Greg FAQ: Process Substitution

ou avec un tube nommé

mkfifo ./p 
diff - p <<< "$string1" & echo "$string2" > p 

Bash Greg FAQ: Working with Named Pipes

canal nommé est également connu comme un FIFO. Le - seul est pour l'entrée standard.

<<< est une "chaîne de caractères".

& est comme ; mais met en arrière-plan

+3

+1 pour la réponse correcte. +1 pour une bonne explication des symboles. De plus, la FAQ de Bash de Greg est passée à: http://mywiki.wooledge.org/ Les liens pour les pages ci-dessus sont maintenant à http://mywiki.wooledge.org/ProcessSubstitution et http://mywiki.wooledge.org/ BashFAQ/085 – timemachine3030

+0

thx! et aussi, cela montrera les descripteurs de fichiers dynamiques 'FUNC() {echo" $ @ "; "$ @"; } FUNC diff <(echo a) <(echo b); ' –

+0

Je cherchais ça pour faire deux shasums. Je ne sais pas s'il existe une façon plus élégante de le faire, mais cela fonctionne. – fuma

11

Je préfère cmp et processus Remplacement fonction de bash:

$ cmp -bl <(echo -n abcda) <(echo -n aqcde) 
    2 142 b 161 q 
    5 141 a 145 e 

Dire sur la position 2, ab se produit pour la première, mais aq pour la seconde. En position 5, une autre différence est en train de se produire. Remplacez simplement ces chaînes par des variables, et vous avez terminé.

+0

Cela ne fonctionne que lorsque les chaînes ont la même longueur! – strpeter

8

Supposons que vous avez trois cordes

a="this is a line" 
b="this is" 
c="a line" 

Pour supprimer le préfixe b d'un

echo ${a#"$b"} 

Pour supprimer le suffixe c d'un

echo ${a%"$c"} 
+1

Je suppose que c'est la façon de le faire. Cela a bien fonctionné. Cette syntaxe est un peu difficile à comprendre. –

+0

@MikaelRoos D'accord. Plus facile à lire (pour moi quand même) serait d'utiliser sed: 'echo" $ a "| sed "s!^$ b !! g" '(J'ai échangé le séparateur sed standard/for! dans le cas où les variables traitées sont des chemins.En outre, vous pouvez utiliser une chaîne ici à la place de echo:' sed ... <<< $ a'.) –