Wie kann ich den Wert einer Pipe im Testprogramm verwenden?


10
wc -l | test -eq 1

Das funktioniert nicht. Ich möchte das Ergebnis von wc mit dem Wert 1 vergleichen. Wie kann ich das tun?

Antworten:


8

Ihre Frage zu Rohren wird nicht beantwortet, aber Sie können Folgendes neu anordnen:

test $(ls -l | wc -l) -eq 1 && echo "worked"

Und es gibt ein paar Lösungen für SO , das ist das Schönste:

ls -l | wc -l | { read wc; test $wc -eq 7 && echo "woohoo"; }

4

Wenn Sie Bash verwenden, möchten Sie wahrscheinlich die Variable PIPESTATUS untersuchen. Wie im Bash-Referenzhandbuch angegeben , ist PIPESTATUS

Eine Array-Variable (siehe Arrays), die eine Liste der Exit-Statuswerte der Prozesse in der zuletzt ausgeführten Vordergrund-Pipeline enthält (die möglicherweise nur einen einzigen Befehl enthält).

Mit PIPESTATUS können wir herausfinden, wie die Exit-Codes für diese Pipeline lauteten:

dmesg | grep -iw 'nnse' | wc -l

Wenn Sie jetzt die Array-Variable abfragen, erhalten Sie die Exit-Status, die sich auf die in der Pipeline verwendeten Befehle beziehen:

echo ${PIPESTATUS[@]}
0 1 0

(In einem indizierten Array werden diese Exit-Codes im Array durch 0 1 und 2 dargestellt, da Arrays in Bash immer bei 0 beginnen.)

Hier sehen wir, dass der zweite Befehl 1 und der Rest 0 zurückgibt; jedoch wc -lgibt 0 zurück , wenn es Null Streichhölzer, was kein Fehler ist. Der Fehler wird mit einem Wert ungleich Null dargestellt, und es gibt andere Fehlerwerte wie 127, bei denen der Befehl nicht gefunden wurde, und noch mehr Codes, die für das betreffende Programm spezifisch sein können.

Wenn Sie sehen möchten, wie der Exit-Code eines bestimmten Befehls in der Pipeline lautete, können Sie einfach auf diesen Wert zugreifen. Der Befehl grep war der zweite Befehl in der obigen Pipeline, aber da Arrays bei 0 beginnen, benötigen wir den ersten Eintrag.

Um den Exit-Code des Befehls grep herauszufinden, führen Sie die obige Pipeline erneut aus (da der Inhalt von PIPESTATUS erschöpft ist, wenn Sie ausgeführt haben echo ${PIPESTATUS[@]}), und führen Sie dann den folgenden Befehl aus, der 1 (den Exit-Code) zurückgibt :

echo ${PIPESTATUS[1]}
1

Stellen Sie in einem Skript sicher, dass die Ausführung der Pipeline abgeschlossen ist, bevor Sie den Inhalt der Array-Variablen PIPESTATUS suchen.

Ein Beispiel für eine interessante Verwendung der Array-Variablen PIPESTATUS finden Sie in dieser Antwort zum Kombinieren der Bash-Befehlsgruppierung und des Pipe-Status . Sie können die Array-Variable auf die von Gilles in den Kommentaren vorgeschlagene Weise testen, obwohl Sie zuerst die Pipeline erneut ausführen müssen:

dmesg | grep -iw 'nnse' | wc -l
[ ${PIPESTATUS[1]} -eq 1 ] && do_something_here

Dies ist nur ein Fragment, da ich nicht weiß, welche Art von Skript Sie beabsichtigen, aber ich hoffe, dass das Wissen über PIPESTATUS für Sie von Nutzen sein kann. Es gibt viele Bash-Array-Variablen wie PIPESTATUS, die äußerst nützlich sein können. Beispiele für ihre Verwendung finden Sie im Bash-Referenzhandbuch für die gesamte Liste und auf den anderen Stackexchange-Sites.


1

Dies deckt nicht jeden testFall ab, aber wenn Sie einen regulären Ausdruck und grepdie Pipeline-Zeichenfolge verwenden können, ist dies ziemlich einfach, da grepes testähnlich ist, dass es einen Exit ungleich Null hat, wenn keine Übereinstimmung gefunden wird

cat file | wc -l | grep -qE '^\s*1\s*$'

Mit erweiterten regulären Ausdrücken können Sie mit dieser Technik viele Fälle abdecken. Für Kichern ein Testfall:

for i in 1 11 '' foo; do 
  if echo $i | grep -qE '^\s*1\s*$'; then 
    echo "'$i' matched"
  else
    echo "'$i' didn't match."
  fi
done

Ausgänge:

'1' matched
'11' didn't match.
'' didn't match.
'foo' didn't match.

1

Der einfachste Weg ist wahrscheinlich die Verwendung von xargs :

wc -l | xargs -I % test % -eq 1
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.