web-dev-qa-db-fra.com

Bash: une ligne pour quitter avec le statut opposé d'une commande grep?

Comment puis-je réduire le script bash suivant?

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

Il semble que je devrais être capable de le faire avec une seule commande, mais j'ai un total de 3 ici.

Mon programme devrait:

  • Lire recess.txt
  • Sortie 1 (ou non nulle) si elle contient une ligne avec "STATUS:" de NOT "Perfect"
  • Sortie 0 si aucune ligne de ce type n’existe (c’est-à-dire que toutes les lignes "STATUS:" sont "parfaites")

Le prix de la réponse va au script le plus serré. Merci!

Fichiers d'exemple

Le programme doit avoir le statut de sortie 0 pour ce fichier:

FILE: styles.css 
STATUS: Perfect!

FILE: contour-styles.css
STATUS: Perfect!

Le programme doit avoir le statut de sortie 1 (ou différent de zéro) pour ce fichier:

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

Juste annulez la valeur de retour.

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

Je suis tombé sur cette question, nécessitant une déclaration onlyif pour Puppet. En tant que tel, la solution bash de Tgr ne fonctionnerait pas, et je ne voulais pas développer la complexité comme dans la réponse de Christopher Neylan .

J'ai fini par utiliser une version inspirée de la réponse de Henri Schomäcker , mais notamment simplifiée:

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

Ce qui très simplement inverse le code de sortie, en renvoyant succès uniquement si le texte n'est pas trouvé:

  • Si grep renvoie 0 (correspondance trouvée), test 0 -eq 1 renverra 1.
  • Si grep renvoie 1 (aucune correspondance), test 1 -eq 1 renverra 0.
  • Si grep renvoie 2 (erreur), test 2 -eq 1 renverra 1.

Ce qui est exactement ce que je voulais: renvoyer 0 si aucune correspondance n'est trouvée, et 1 sinon.

10
cincodenada

Pour que cela fonctionne avec set -e, placez-le dans un sous-shell avec ( et ):

$ 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

En réalité, vous n'avez pas du tout besoin d'utiliser exit. Logiquement, quel que soit le résultat de grep, votre script va quand même sortir. Étant donné que la valeur de sortie d'un script Shell est le code de sortie de la dernière commande exécutée, il suffit d'exécuter grep comme dernière commande, en utilisant l'option -v pour inverser la correspondance afin de corriger la valeur de sortie. Ainsi, votre script peut réduire à seulement:

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

MODIFIER:

Désolé, ce qui précède ne fonctionne pas lorsqu'il existe d'autres types de lignes dans le fichier. Cependant, dans l’intérêt d’éviter d’exécuter plusieurs commandes, awk peut accomplir l’ensemble du Shebang avec quelque chose comme:

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

Si vous décidez que vous voulez la sortie que grep aurait fournie, vous pouvez faire:

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

si quelqu'un arrive ici à la recherche d'une manipulation du code de retour Bash:

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

cela renverra 0 (succès) lorsque grep ne trouvera rien, et renverra 123 (échec) quand ce sera le cas. Les parenthèses sont au cas où quelqu'un le testerait tel quel sur l'invite du shell. avec des parenthèses, il ne se déconnectera pas à la sortie, mais simplement quitter le sous-shell avec le même code d'erreur.

je l'utilise pour une vérification rapide de la syntaxe sur les fichiers js:

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

La simple négation de la valeur de retour ne fonctionne pas dans un contexte -e défini. Mais vous pouvez faire:

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

Utilisez la variable spéciale ? :

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

(Mais notez que grep peut aussi renvoyer 2, il est donc difficile de savoir ce que vous souhaiteriez dans de tels cas.)

1

Le problème avec les réponses de grep est que si le fichier est vide, vous obtenez également une réponse propre, comme si le fichier avait une image parfaite.

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

J'avais également besoin d'une telle solution pour écrire des marionnettes uniquement si des déclarations et proposait la commande suivante:

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

0
Henri Schomäcker