Comment puis-je utiliser la valeur d'un tuyau dans le programme de test?

10
wc -l | test -eq 1

Ça ne marche pas. Je veux comparer le résultat de wc avec la valeur de 1. Comment faire?

tr3quart1sta
la source

Réponses:

9

Cela ne répond pas à votre question sur les tuyaux, mais vous pouvez réorganiser:

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

Et il y a quelques solutions sur SO , ce qui est le plus agréable:

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

Si vous utilisez Bash, vous souhaiterez probablement rechercher la variable PIPESTATUS. Comme indiqué dans le guide de référence Bash , PIPESTATUS est

Une variable de tableau (voir Tableaux) contenant une liste des valeurs de statut de sortie des processus dans le pipeline de premier plan le plus récemment exécuté (qui ne peut contenir qu'une seule commande).

Nous pouvons découvrir quels étaient les codes de sortie pour ce pipeline avec PIPESTATUS:

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

Si vous interrogez maintenant la variable de tableau, vous obtenez les états de sortie faisant référence aux commandes utilisées dans le pipeline:

echo ${PIPESTATUS[@]}
0 1 0

(Dans un tableau indexé, les codes de sortie ci-dessus sont représentés par 0 1 et 2 dans le tableau car les tableaux commencent toujours à 0 dans Bash.)

Ici, nous voyons la deuxième commande renvoyé 1, et le reste 0; cependant, wc -lrenvoie 0 s'il n'y a aucune correspondance, ce qui n'est pas une erreur. L'échec est représenté par une valeur non nulle, et il existe d'autres valeurs d'erreur telles que 127 qui est une commande non trouvée, et encore plus de codes qui peuvent être spécifiques au programme concerné.

Si vous voulez voir quel était le code de sortie d'une commande particulière dans le pipeline, vous pouvez simplement accéder à cette valeur. La commande grep était la deuxième commande dans le pipeline ci-dessus, mais comme les tableaux commencent à 0, nous avons besoin de l'entrée un.

Donc, pour découvrir le code de sortie de la commande grep, exécutez à nouveau le pipeline ci-dessus (car le contenu de PIPESTATUS aura été épuisé si vous l'avez exécuté echo ${PIPESTATUS[@]}), puis exécutez la commande ci-dessous, qui renverra 1 (le code de sortie):

echo ${PIPESTATUS[1]}
1

Dans un script, assurez-vous que l'exécution du pipeline est terminée avant de rechercher le contenu de la variable de tableau PIPESTATUS.

Pour un exemple d'utilisation intéressante de la variable de tableau PIPESTATUS, consultez cette réponse concernant la combinaison du regroupement de commandes Bash et de l'état du canal . Vous pouvez tester la variable tableau de la manière suggérée par Gilles dans les commentaires, bien que vous deviez d'abord réexécuter le pipeline:

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

Ce n'est qu'un fragment, car je ne sais pas quel type de script vous envisagez, mais j'espère que connaître PIPESTATUS pourra vous être utile. Il existe de nombreuses variables de tableau Bash comme PIPESTATUS qui peuvent être extrêmement utiles; voir le guide de référence Bash pour la liste complète, et les autres sites Stackexchange pour des exemples de leur utilisation.

Communauté
la source
2

La façon la plus simple est probablement d'utiliser xargs :

wc -l | xargs -I % test % -eq 1
John Doe
la source
1

Cela ne couvre pas tous les testcas, mais si vous pouvez utiliser une expression régulière et grepla chaîne canalisée, c'est assez simple car il grepest testsimilaire à ce qu'il a une sortie non nulle lorsqu'aucune correspondance n'est trouvée

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

Les expressions régulières étendues vous permettent de couvrir de nombreux cas avec cette technique. Pour les rires, un cas de test:

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

les sorties:

'1' matched
'11' didn't match.
'' didn't match.
'foo' didn't match.
zanerock
la source