it-swarm.com.de

Bash: Einzeiler zum Beenden mit dem entgegengesetzten Status eines grep-Befehls?

Wie kann ich das folgende Bash-Skript reduzieren?

grep -P "STATUS: (?!Perfect)" recess.txt && exit 1
exit 0

Es scheint, als ob ich es mit einem einzigen Befehl tun könnte, aber ich habe insgesamt 3 hier.

Mein Programm sollte:

  • Lies Pause.txt
  • Beenden Sie 1 (oder nicht Null), wenn es eine Zeile mit "STATUS:" von NOT "Perfect" enthält
  • Verlasse 0, wenn keine solche Zeile existiert (d. H. Alle "STATUS:" - Zeilen sind "Perfekt")

Der Antwortpreis geht an das engste Drehbuch. Vielen Dank!

Beispieldateien

Das Programm sollte den Status 0 verlassen für diese Datei:

FILE: styles.css 
STATUS: Perfect!

FILE: contour-styles.css
STATUS: Perfect!

Das Programm sollte Exit-Status 1 (oder nicht Null) für diese Datei haben:

FILE: styles.css 
STATUS: Perfect!

FILE: contour-styles.css
STATUS: Busted 
FAILURES: 1 failure

Id's should not be styled
       1. #asdf
25
Sean Adkinson

Einfach negieren den Rückgabewert.

! grep -P "STATUS: (?!Perfect)" recess.txt
25
Tgr

Ich bin darauf gestoßen und brauchte eine onlyif-Anweisung für Puppet. Als solches würde Tgrs bash-Lösung nicht funktionieren, und ich wollte die Komplexität nicht erweitern, wie in Christopher Neylans Antwort .

Am Ende habe ich eine Version verwendet, die von Henri Schomäcker's Antwort inspiriert wurde aber vor allem vereinfacht:

grep -P "STATUS: (?!Perfect)" recess.txt; test $? -eq 1

Dadurch wird der Exit-Code sehr einfach invertiert und der Erfolg wird nur zurückgegeben, wenn der Text nicht gefunden wird:

  • Wenn grep 0 (Übereinstimmung gefunden) zurückgibt, gibt test 0 -eq 1 1 zurück.
  • Wenn grep 1 zurückgibt (keine Übereinstimmung gefunden), gibt test 1 -eq 1 0 zurück.
  • Wenn grep 2 (Fehler) zurückgibt, gibt test 2 -eq 1 1 zurück.

Welches ist genau das, was ich wollte: Gib 0 zurück, wenn keine Übereinstimmung gefunden wird, und 1 sonst.

10
cincodenada

Damit es mit set -e funktioniert, umgeben Sie es in einer Sub-Shell mit ( und ):

$ cat test.sh 
#!/bin/bash

set -ex
(! ls /tmp/dne)
echo Success
$ ./test.sh 
+ ls /tmp/dne
ls: cannot access /tmp/dne: No such file or directory
+ echo Success
Success
$ mkdir /tmp/dne
$ ./test.sh 
+ ls /tmp/dne
$ 
7
Robpol86

Sie brauchen exit eigentlich gar nicht. Logisch, egal was das Ergebnis von grep ist, Ihr Skript wird trotzdem beendet. Da der Exit-Wert eines Shell-Skripts der Exit-Code des zuletzt ausgeführten Befehls ist, müssen Sie lediglich grep als letzten Befehl ausführen. Verwenden Sie die -v-Option, um die Übereinstimmung umzukehren, um den Exit-Wert zu korrigieren. So kann Ihr Skript auf Folgendes reduzieren:

grep -vqP "STATUS: (?!Perfect)" recess.txt

BEARBEITEN:

Leider funktioniert das oben nicht, wenn die Datei andere Zeilenarten enthält. Um zu vermeiden, dass mehrere Befehle ausgeführt werden, kann awk den gesamten Shebang mit etwas wie dem folgenden ausführen:

awk '/STATUS: / && ! /Perfect/{exit 1}' recess.txt

Wenn Sie sich für die von grep bereitgestellte Ausgabe entscheiden, können Sie Folgendes tun:

awk '/^STATUS: / && ! /Perfect/{print;ec=1} END{exit ec}' recess.txt
6

wenn hier jemand nach einer Bash-Rückkehrcode-Manipulation sucht:

(grep <search> <files> || exit 0 && exit 123;)

dies gibt 0 (Erfolg) zurück, wenn grep nichts findet, und gibt 123 (Fehler) zurück, wenn dies der Fall ist. Die Klammern sind für den Fall, dass jemand es wie auf der Shell-Eingabeaufforderung prüft. Mit Klammern wird es sich beim Exit nicht abmelden, sondern die Subshell mit demselben Fehlercode beenden.

ich verwende es für eine schnelle Syntaxprüfung von JS-Dateien:

find src/js/ -name \*js -exec node \{\} \; 2>&1 | grep -B 5 SyntaxError || exit 0 && exit 1;
5
gcb

Das Negieren des Rückgabewerts funktioniert nicht in einem Set-e-Kontext. Aber du kannst tun:

! grep -P "STATUS: (?!Perfect)" recess.txt || false
4
Eric Woodruff

Verwenden Sie die special ? Variable :

grep -P "STATUS: (?!Perfect)" recess.txt
exit $((1-$?))

(Beachten Sie jedoch, dass grep auch 2 zurückgeben kann. Daher ist nicht klar, was in solchen Fällen vorkommen soll.)

1

Das Problem mit den grep-Antworten ist, dass, wenn die Datei leer ist, Sie auch eine saubere Antwort erhalten, als hätte die Datei eine perfekte. Also habe ich persönlich auf grep verzichtet und es mit awk verwendet.

awk 'BEGIN{ef=2}; /STATUS: Perfect/{ ef=0;}; /STATUS: Busted/{ print;eff=3;}; END{exit (ef+eff)}' a.txt ; echo $?

This has exit status:
 0 :  Perfect and !Busted
 2 : !Perfect and  Busted
 3 :  Perfect and  Busted
 5 : !Perfect and !Busted
1
M Hutson
[ $(grep -c -P "STATUS: (?!Perfect)" recess.txt) -eq 0 ]
0
Chris

Ich brauchte eine solche Lösung, um nur Marionetten zu schreiben, wenn Sie mit den folgenden Anweisungen befanden:

/bin/grep --quiet 'root: [email protected]' /etc/aliases; if [ $? -eq 0 ]; then test 1 -eq 2; else test 1 -eq 1; fi;

0