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:
Le prix de la réponse va au script le plus serré. Merci!
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
Juste annulez la valeur de retour.
! grep -P "STATUS: (?!Perfect)" recess.txt
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é:
test 0 -eq 1
renverra 1.test 1 -eq 1
renverra 0.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.
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
$
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
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;
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
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.)
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
[ $(grep -c -P "STATUS: (?!Perfect)" recess.txt) -eq 0 ]
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;