Lorsque le code d'état est inutile, existe-t-il de toute façon de construire un pipeline basé sur la sortie de stdout?
Je préférerais que la réponse ne traite pas du cas d'utilisation, mais de la question relative à la portée des scripts shell. Ce que j'essaie de faire, c'est de trouver le package le plus spécifique disponible dans le référentiel en devinant le nom en fonction des codes de pays et de langue.
Prenez par exemple ceci,
$PACKAGE1=hunspell-en-zz
$PACKAGE2=hunspell-en
La première supposition est plus appropriée mais elle peut ne pas exister. Dans ce cas, je veux retourner hunspell-en
( $PACKAGE2
) car la première option hunspell-en-zz
( $PACKAGE1
) n'existe pas .
pipelines d'apt-cache
La commande apt-cache
renvoie succès (qui est défini par shell comme code de sortie zéro) chaque fois que la commande est en mesure de s'exécuter (à partir des documents de apt-cache
)
apt-cache renvoie zéro en fonctionnement normal, 100 décimal en cas d'erreur.
Cela rend l'utilisation de la commande dans un pipeline plus difficile. Normalement, je m'attends à ce que l'équivalent de recherche de package d'un 404 entraîne une erreur (comme cela se produirait avec curl
ou wget
). Je veux rechercher pour voir si un paquet existe, et sinon, revenir à un autre paquet s'il existe .
Cela ne renvoie rien, car la première commande retourne le succès (donc le rhs dans le ||
ne s'exécute jamais)
apt-cache search hunspell-en-zz || apt-cache search hunspell-en
apt-cache search
avec deux arguments
Cela ne renvoie rien, comme apt-cache
ANDs ses arguments,
apt-cache search hunspell-en-zz hunspell-en
D'après les documents de apt-cache
Des arguments séparés peuvent être utilisés pour spécifier plusieurs modèles de recherche qui sont and'és ensemble.
Donc, comme l'un de ces arguments n'existe clairement pas, cela ne renvoie rien.
La question
Quel est l'idiome du shell pour gérer des conventions comme celles trouvées apt-cache
là où le code de retour est inutile pour la tâche? Et le succès n'est déterminé que par la présence de sortie sur STDOUT?
Semblable à
faire échouer quand rien n'a été trouvé
ils découlent tous deux du même problème. La réponse choisie y mentionne
find -z
ce qui n'est malheureusement pas applicable ici et est spécifique au cas d'utilisation. Il n'y a aucune mention d'un idiome ou de la construction d'un pipeline sans utiliser la terminaison nulle (pas une option surapt-cache
)
la source
hunspell-en
existe? Quoi qu'il en soit, vous pouvez utiliserapt-cache policy
et grep for^$PACKAGENAME:
.hunspell-ar
existe et il n'y a pas de packages de noms de pays. J'ai besoin de trouver le package le plus précis pour un pays et une langue donnés.find
est commeapt-cache
à cet égard - code retour inutile, le succès est basé sur la sortie.-z
ce qui n'est malheureusement pas une solution ici, donc le problème spécifique au cas d'utilisation n'est pas applicable. Et il n'y a aucune mention d'un idiome ou de la construction d'un pipeline sans utiliser la terminaison nulle (pas une option surapt-cache
)find
à être utilisé avec-print0
et donc à utiliser-z
. Puisque apt-cache ne donne pas de sortie terminée par null, vous n'en avez pas besoin-z
.Réponses:
Créez une fonction qui prend une commande et renvoie true si elle a une sortie.
Donc, pour ce cas d'utilisation, cela fonctionnera comme ceci,
la source
r printf '\n\n\n'
cela retournerait faux. Avec des obus autres quezsh
,r printf '\0\0\0'
reviendrait également faux. Il en serait de mêmer printf '\0a\0b\0c'
pour certains obus.Pour autant que je sache, il n'existe aucun moyen standard de traiter les cas où le succès d'une commande est déterminé par la présence de sortie. Vous pouvez cependant écrire des solutions de contournement.
Par exemple, vous pouvez enregistrer la sortie de la commande dans une variable, puis vérifier si cette variable est vide ou non:
Je pense que cela répond à la question d'une manière générale, mais si nous parlons de
apt-cache search
certaines solutions me viennent à l'esprit.J'ai un script qui facilite la gestion des packages. Certaines de ses fonctions sont les suivantes:
Ceux-ci vous permettent d'effectuer plusieurs recherches en une seule commande. Par exemple:
Chaque fonction recherche la base de données d'une manière différente, donc les résultats peuvent varier selon la fonction que vous utilisez:
la source
Je n'appellerais pas cela élégant mais je pense que cela pourrait faire l'affaire:
Je n'ai malheureusement pas de machine Debian sur laquelle tester. J'ai inclus l'
-n
option for "names-only"apt-cache
pour essayer de limiter les résultats de la recherche car il semble que vous soyez presque sûr de ce que vous recherchez.Peut être exécuté comme:
la source
-q
option silencieuse? La page de manuel n'est pas très détaillée, mais peut-être qu'elle modifie les valeurs de retour?Muru a précisé cela dans les commentaires
grep
renverra un état de 1 s'il n'y a pas d'entrée. Vous pouvez donc ajoutergrep .
dans le flux et s'il n'y a pas d'entrée correspondant au modèle.
, cela changera le code d'état:Dans le cas d'utilisation qui ressemble à ceci. Dans le bas, il n'y a pas
-pl-pl
donc il retombe et revienthunspell-pl
Ou,
Il y a
-en-US
donc un retourhunspell-en-us
.Voir également,
la source
grep .
renvoie true si l'entrée contient au moins une ligne (entièrement délimitée avec certaines implémentations) qui contient au moins un caractère (bien formé avec la plupart des implémentations) et supprimera sinon les lignes vides.grep '^'
fonctionnerait mieux pour vérifier qu'il y a une sortie, mais avec une implémentation, elle pourrait toujours retourner false si l'entrée est une ligne non délimitée (et pourrait supprimer cette ligne, ou avec d'autres implémentations, retourner true mais ajouter la nouvelle ligne manquante). Certaines implémentations grep étouffent également le caractère NUL.Vous pouvez définir un:
Et alors:
Certaines
awk
implémentations peuvent s'étouffer avec des caractères NUL dans l'entrée.Contrairement à
grep '^'
, ce qui précède serait garanti pour fonctionner sur une entrée qui ne se termine pas par un caractère de nouvelle ligne, mais ajouterait la nouvelle ligne manquante.Pour éviter cela et être portable sur des systèmes où
awk
s'étouffent NUL, vous pouvez utiliser à laperl
place:Avec
perl
, vous pouvez également définir une variante qui gère plus élégamment les fichiers arbitraires:Cela limite l'utilisation de la mémoire (comme pour les fichiers qui n'ont pas de caractères de nouvelle ligne comme les gros fichiers épars).
Vous pouvez également créer des variantes comme:
ou:
(attention, la définition du blanc varie entre les
awk
implémentations, certaines où elles sont limitées à l'espace et à la tabulation, d'autres où elles incluent également des caractères d'espacement vertical ASCII comme CR ou FF, d'autres où elle considère les blancs des paramètres régionaux)Idéalement, sous Linux, vous souhaitez utiliser l'
splice()
appel système pour maximiser les performances. Je ne sais pas d'une commande qui exposerait mais vous pouvez toujours utiliserpython
estctypes
:(notez que soit
has_output
stdin soit stdout (ou les deux) doit être un tube poursplice()
fonctionner).la source
Je suggère d'utiliser des fonctions intégrées très basiques du shell:
Voici le cas de test le plus simple:
Ensuite, vous pouvez facilement l'utiliser avec la
||
construction à laquelle vous êtes habitué:Cette fonction simple fonctionnera comme vous le souhaitez avec votre
apt_cache
comportement, quel que soit le nombre d'arguments.la source
ck_command echo 'asdf' | cat
ne produit rien.