So speichern Sie die Ausgabe eines Befehls (z. B. diff) in einer Variablen

21

Ich möchte testen, ob es eine Ausgabe von gibt diff(testen, ob Dateien identisch sind), wenn keine echo "Passed $x" else echo "Failed $x". Ich habe mir einen Zwischenschritt ausgedacht (speichere die Ausgabe von diff in eine Datei und lese sie dann aus der Datei)

diff "./helloworld$x.out" "./output/helloworld$x.out" > tmp.txt;
output="`cat tmp.txt`";

if [ "$output" = "" ];
  then
    echo "Passed $x";
  else
    echo "Failed $x";
  fi;

Ich bin sicher, dass der Code verbessert werden kann? Die Hauptfrage ist: Ist es möglich, die Ausgabe von diffdirekt in eine Variable zu speichern ?

Jiew Meng
quelle

Antworten:

18

Das funktioniert:

if diff "./helloworld$x.out" "./output/helloworld$x.out"> / dev / null; dann
    echo "Passed $ x";
sonst
    echo "Failed $ x";
fi

Wenn Sie stattdessen eine Variable verwenden, können echoSie die elseVerzweigung löschen: Setzen Sie die Variable vor dem auf false ifund speichern Sie 2 Codezeilen.

Wenn Sie das Ergebnis tatsächlich in eine Variable einfügen möchten, verwenden Sie:

some_var="$(diff "./helloworld$x.out" "./output/helloworld$x.out")"

Einschließlich meines Tests, um zu sehen, ob es tatsächlich funktioniert:

rinzwind @ discworld: ~ $ touch 1
rinzwind @ discworld: ~ $ touch 2
rinzwind @ discworld: ~ $ mehr test
if diff 1 2> / dev / null; dann
    echo "Passed $ x";
sonst
    echo "Failed $ x";
fi
rinzwind @ discworld: ~ $ ./test
Bestanden 

rinzwind @ discworld: ~ $ vi 2
rinzwind @ discworld: ~ $ more 2
2
rinzwind @ discworld: ~ $ ./test
Gescheitert 

Zum >/dev/nullTeil: >/dev/null 2>&1Sendet die Ausgabe an dieselbe Datei >/dev/nullund 2>&1sendet Standardfehler an dieselbe Datei ( &1bedeutet 'Erste Parameter verwenden') vor diesem Befehl (wird also auch verwendet /dev/null).

Nebenbemerkung: Zeigt sdiffeine diffListe nebeneinander an :

sdiff 1 2 
1 1
2 2
3 3
4 4
5 5
7 7
                                  > 8
9 9
10 10
Rinzwind
quelle
Danke, es funktioniert, aber ich verstehe nicht, was ... > /dev/nullin diesem Zusammenhang tut. Die Ausgabe von diff wird nach / dev / null gehen, aber ist das nicht nichts?
Jiew Meng
1
Der Diff gibt alle Unterschiede zwischen den Dateien auf Ihrem Bildschirm aus und> / dev / null stellt sicher, dass die Ausgabe des Befehls in Vergessenheit gerät. Das if wird basierend auf der Ausgabe noch ausgeführt.
Rinzwind
1
Die if-Anweisung überprüft den Exit-Code des diff-Befehls. 0 bedeutet, dass keine Unterschiede gefunden wurden, während 1 bedeutet, dass es einen oder mehrere Unterschiede gab.
Knut Eldhuset
17

diff Die Ausgabe kann sogar vollständig unterdrückt werden, mit Ausnahme der Meldung "Dateien / bin / bash und / bin / sh unterscheiden", die den folgenden Code verwendet.

file1="./helloworld$x.out"
file2="./output/helloworld$x.out"

if diff -q "$file1" "$file2"; then
    echo "Passed $x"
else
    echo "Failed $x"
fi

Wenn Sie diese Nachricht sogar ausblenden möchten, müssen Sie > /dev/nullnach dem Befehl diff Folgendes anfügen , um die Ausgabe von diff:

if diff -q "$file1" "$file2" >/dev/null; then

/dev/null ist eine spezielle Datei, die als Schwarzes Loch fungiert. Wenn Sie darauf schreiben, ist sie verschwunden. Wenn Sie davon lesen, erhalten Sie nichts zurück.

Beachten Sie, dass bash keine ;Zeilenenden benötigt.

Wie für die ursprüngliche Frage, um die Ausgabe eines Programms in einer Variablen zu speichern:

file1="./helloworld$x.out"
file2="./output/helloworld$x.out"
output="$(diff -q "$file1" "$file2")"

# the quotes are mandatory, this checks whether $output is empty or not
if [ -n "$output" ]; then
    echo "Passed $x"
else
    echo "Failed $x"
fi

Alternative Möglichkeiten, um zu überprüfen, ob eine Variable leer ist:

[ "$output" = "" ]
[ "$output" == "" ]
[[ "$output" == "" ]]
[[ $output == "" ]]

Wenn Sie Bash verwenden, werden die letzten beiden Befehle für den Zeichenfolgenvergleich empfohlen. Ansonsten ist das erste und [ -n "$output" ]empfohlen.

Lekensteyn
quelle
6

a) Die Ausgabe von command1 kann mit abgefangen werden

output=$(diff "helloworld$x.out" "output/helloworld$x.out") 

oder mit Backticks, aber von diesen wird abgeraten, da Sie sie nicht verschachteln können und sie je nach Schriftart schwer von Apostrophen zu unterscheiden sind:

 output=`cmd1`

b) Anstatt in eine Datei zu schreiben und diese dann zu lesen (oder die Ausgabe zu erfassen und dann zu wiederholen), würden Sie eine Pipe direkt verwenden:

 cmd1 > file
 cat file | cmd2 

 output=$(cmd1)
 echo "${output}" | cmd2 

=>

 cmd1 | cmd2 

Aber in Ihrem Beispiel interessiert Sie nicht die Ausgabe, sondern das Ergebnis des Programms - hat es funktioniert?

 diff "helloworld$x.out" "output/helloworld$x.out" && echo "success" || echo "failure" 

Lesen Sie mehr über die Verwendung von && und || Suche nach "Verknüpfung UND und Verknüpfung ODER".

Um die Ausgabe sauber zu halten, können Sie die Ausgabe von 'diff' an einen anderen Ort umleiten:

 diff "helloworld$x.out" "output/helloworld$x.out" >/dev/null && echo "success" || echo "failure" 

Um Erfolg zu haben und ihn später auszuwerten, speichern Sie das Ergebnis des letzten Befehls in einer Variablen mit $ ?:

diff "helloworld$x.out" "output/helloworld$x.out" >/dev/null
result=$?
# do something else
case $result in 
   0) echo success ;;
   *) echo failure ;;
esac
Benutzer unbekannt
quelle
3

Wenn Sie wissen möchten, ob zwei Dateien identisch oder unterschiedlich sind (es ist jedoch egal, was der Unterschied tatsächlich ist), cmpist dies besser geeignet.

if cmp -s file1 file2; then echo "Equal"; else echo "Not equal"; fi
geirha
quelle