2009-01-18 9 views
70

Ich versuche einen Weg zu finden, um den Unterschied zwischen zwei Strings in meinem Skript zu bestimmen. Ich könnte das leicht mit diff oder comm machen, aber ich habe es nicht mit Dateien zu tun, und ich würde es vorziehen, sie nicht in Dateien auszugeben, zu vergleichen und zurückzulesen.Bash String Unterschied

Ich sehe, dass comm, diff, cmp alle erlauben, entweder zwei Dateien oder eine Datei und Standard-Eingabe - ich denke, das ist gut, wenn ich nicht zwei Dateien ausgeben will ... aber es ist immer noch irgendwie saugt.

Ich habe herumgegrubbelt und gedacht, ich könnte grep oder reguläre Ausdrücke benutzen - aber ich denke nicht.

Vielen Dank im Voraus,

+1

was wollen Sie eigentlich tun zu entfernen? – hop

+0

Sie können Teilstringmanipulationen und eingebaute Testoperationen mit IFS-Änderungen zum Vergleichen verwenden, aber Sie müssen wissen, ob Sie Zeichen für Zeichen, Wort für Wort, Zeile für Zeile vergleichen, Leerraum ignorieren möchten ... – technosaurus

+0

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

Antwort

9

Erinnert mich an diese Frage: How can you diff two pipelines in Bash?

Wenn Sie in einer Bash-Sitzung sind, könnten Sie tun ein:

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

mit < anonymen Named Pipes zu schaffen - - verwaltet von bash - so werden sie automatisch erstellt und zerstört, im Gegensatz zu temporären Dateien.

Also, wenn Sie verwalten Ihre zwei verschiedene String als Teil eines Befehls zu isolieren (grep, awk, sed, ...), können Sie tun - zum Beispiel - so etwas wie:

diff < grep string1 myFile < grep string2 myFile 

(wenn Sie nehme an, Sie in Ihrer Datei Zeilen haben wie string1=very_complicated_value und ein string2=another_long_and_complicated_value': ohne das interne Format der Datei zu kennen, ich keinen genauen Befehl empfehlen kann)

124

mit diff oder com oder was auch immer Sie wollen:

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

Gregs Bash FAQ: Process Substitution

oder mit einem Named Pipe

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

Gregs Bash FAQ: Working with Named Pipes

Named Pipe auch als FIFO bekannt ist.

Das - allein ist für Standardeingabe.

<<< ist eine "hier Zeichenfolge".

& wie ; ist aber bringt es auf den Hintergrund

+3

+1 für die richtige Antwort. +1 für großartige Erklärung der Symbole. Darüber hinaus ist Gregs Bash FAQ umgezogen zu: http://mywiki.wooledge.org/ Die Links für die oben genannten Seiten sind jetzt unter http://mywiki.wooledge.org/ProcessSubstitution und http://mywiki.wooledge.org/ BashFAQ/085 – timemachine3030

+0

Danke! Außerdem zeigt dies die dynamischen Dateideskriptoren 'FUNC() {echo" $ @ "; "$ @"; }; FUNC diff <(echo a) <(echo b); ' –

+0

Ich war auf der Suche nach dem Vergleich zweier Shasums. Ich bin mir nicht sicher, ob es einen eleganteren Weg dafür gibt, aber es funktioniert. – fuma

11

Ich ziehe cmp und Prozess Substitution Merkmal bash:

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

Sagen auf Position 2 tritt ab zum ersten, aber aq für die zweite. An Position 5 ist ein weiterer Unterschied. Ersetzen Sie einfach diese Zeichenfolgen durch Variablen, und Sie sind fertig.

+0

Dies funktioniert nur, wenn Strings die gleiche Länge haben! – strpeter

8

Sagen Sie drei Saiten haben

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

Um Präfix b von einem

echo ${a#"$b"} 

entfernen Suffix c von einem

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

Ich denke, das ist die Bash Art, es zu tun. Es hat gut funktioniert. Diese Syntax ist allerdings schwer zu verstehen. –

+0

@MikaelRoos Vereinbarte. Einfacher zu lesen (für mich sowieso) wäre sed: 'echo" $ a "| sed "s!^$ b !! g" '(Ich habe das Standard-sed-Trennzeichen/für den Fall ausgetauscht, dass die Variablen, die behandelt werden, Pfade sind. Außerdem könnte man hier eine Zeichenfolge anstelle von echo verwenden:' sed ... <<< $ a'.) –