La ifnotemptyfonction suivante redirige son entrée vers la commande passée en argument, sauf qu'elle ne fait rien si l'entrée est vide. Il permet au tuyau source --fooen sink --barpar écrit source --foo | pipe_if_not_empty sink --bar.
Je m'attendrais à ce que cette implémentation fonctionne sur toutes les plates-formes POSIX / Unix, bien ddqu'à proprement parler elle ne soit pas conforme aux normes: elle repose sur le fait de ne pas lire plus que le seul octet qu'on lui a dit de lire sur son entrée standard.
Je pense que ce head -c 1serait un remplacement approprié pour dd bs=1 count=1 2>/dev/nullLinux.
D'un autre côté, head -n 1ne conviendrait pas, car il met headgénéralement en mémoire tampon son entrée et peut lire plus que la seule ligne qu'il sort - et comme il lit à partir d'un canal, les octets supplémentaires sont simplement perdus.
read -r headet même read -r -n 1 headne conviennent pas ici parce que si le premier caractère est une nouvelle ligne, headserait défini sur la chaîne vide, ce qui rend impossible la distinction entre une entrée vide et une entrée commençant par une ligne vierge.
Nous ne pouvons pas simplement écrire head=$(head -c 1)parce que si le premier caractère est une nouvelle ligne, la substitution de commande supprimerait la nouvelle ligne finale, ce qui rendrait impossible la distinction entre une entrée vide et une entrée commençant par une ligne vierge.
En bash, ksh ou zsh, vous pouvez remplacer catpar </dev/stdinpour un gain de performance microscopique.
Si cela ne vous dérange pas de stocker la totalité des données intermédiaires en mémoire, voici une implémentation très légèrement plus simple de pipe_if_not_empty.
Voici une implémentation légèrement plus simple avec les mises en garde suivantes:
Les données produites par la source sont considérées comme vides si et seulement si elles se composent uniquement de caractères de nouvelle ligne. (Cela peut en fait être souhaitable.)
Les données introduites dans le récepteur se terminent par exactement un caractère de nouvelle ligne, quel que soit le nombre de nouvelles lignes avec lesquelles se terminent les données produites par la source. (Cela pourrait être un problème.)
Encore une fois, toutes les données sont stockées en mémoire.
$ echo -e "\n\n"| xargs -r ls
$ # No output. ls did not run.
$ echo -e "\n\n1"| xargs -r ls
ls: cannot access 1:No such file or directory
C'est simple mais ça devrait marcher pour vous. Si votre "une fonction" envoie une chaîne vide ou même une nouvelle ligne dans le pipeline, xargs -r, empêchera le passage à "une autre fonction".
ifne (1) de moreutils fait exactement cela. Moreutils est disponible sous forme de package au moins dans Debian et Ubuntu, probablement dans d'autres distributions également.
La fonction ci-dessous essaie de lire le 1er octet, et si elle réussit, elle fait écho à cet octet et renvoie le reste. Doit être efficace et 100% portable.
Cette fonction échoue pour moi lorsque je cours echo -en "\nX" | pipe_if_not_empty mail -s "Subject line here" [email protected]. Il pense que lineet heresont tous deux destinataires de l'e-mail, pas des jetons dans le sujet. Je dois échapper au "sujet environnant pour le faire fonctionner. Cependant, la pipe_if_not_emptyfonction de la réponse acceptée fonctionne pour moi même sans rien échapper.
kuzzooroo
2
Au moins quelque chose comme ça fonctionne:
yourcommand | if [ $(wc -c) -gt "0" ]; then yourothercommand; fi
Veuillez noter que ce qui précède considérera les sauts de ligne et autres caractères spéciaux comme sortie, donc une ligne vide passée à cette instruction if sera considérée comme une sortie. Augmentez simplement la limite -gt si votre sortie doit généralement être supérieure à 1 octet :)
Réponses:
La
ifnotempty
fonction suivante redirige son entrée vers la commande passée en argument, sauf qu'elle ne fait rien si l'entrée est vide. Il permet au tuyausource --foo
ensink --bar
par écritsource --foo | pipe_if_not_empty sink --bar
.Notes de conception:
dd
qu'à proprement parler elle ne soit pas conforme aux normes: elle repose sur le fait de ne pas lire plus que le seul octet qu'on lui a dit de lire sur son entrée standard.head -c 1
serait un remplacement approprié pourdd bs=1 count=1 2>/dev/null
Linux.head -n 1
ne conviendrait pas, car il methead
généralement en mémoire tampon son entrée et peut lire plus que la seule ligne qu'il sort - et comme il lit à partir d'un canal, les octets supplémentaires sont simplement perdus.read -r head
et mêmeread -r -n 1 head
ne conviennent pas ici parce que si le premier caractère est une nouvelle ligne,head
serait défini sur la chaîne vide, ce qui rend impossible la distinction entre une entrée vide et une entrée commençant par une ligne vierge.head=$(head -c 1)
parce que si le premier caractère est une nouvelle ligne, la substitution de commande supprimerait la nouvelle ligne finale, ce qui rendrait impossible la distinction entre une entrée vide et une entrée commençant par une ligne vierge.cat
par</dev/stdin
pour un gain de performance microscopique.Si cela ne vous dérange pas de stocker la totalité des données intermédiaires en mémoire, voici une implémentation très légèrement plus simple de
pipe_if_not_empty
.Voici une implémentation légèrement plus simple avec les mises en garde suivantes:
Encore une fois, toutes les données sont stockées en mémoire.
la source
Cela devrait fonctionner pour vous
Un exemple
C'est simple mais ça devrait marcher pour vous. Si votre "une fonction" envoie une chaîne vide ou même une nouvelle ligne dans le pipeline, xargs -r, empêchera le passage à "une autre fonction".
Référence pour xargs: http://www.oreillynet.com/linux/cmd/cmd.csp?path=x/xargs
la source
ifne (1) de moreutils fait exactement cela. Moreutils est disponible sous forme de package au moins dans Debian et Ubuntu, probablement dans d'autres distributions également.
la source
La fonction ci-dessous essaie de lire le 1er octet, et si elle réussit, elle fait écho à cet octet et renvoie le reste. Doit être efficace et 100% portable.
Cas de test:
la source
echo -en "\nX" | pipe_if_not_empty mail -s "Subject line here" [email protected]
. Il pense queline
ethere
sont tous deux destinataires de l'e-mail, pas des jetons dans le sujet. Je dois échapper au"
sujet environnant pour le faire fonctionner. Cependant, lapipe_if_not_empty
fonction de la réponse acceptée fonctionne pour moi même sans rien échapper.Au moins quelque chose comme ça fonctionne:
yourcommand | if [ $(wc -c) -gt "0" ]; then yourothercommand; fi
Veuillez noter que ce qui précède considérera les sauts de ligne et autres caractères spéciaux comme sortie, donc une ligne vide passée à cette instruction if sera considérée comme une sortie. Augmentez simplement la limite -gt si votre sortie doit généralement être supérieure à 1 octet :)
la source
yourothercommand
ne voit jamais la sortie deyourcommand
.Au lieu de
sender | receiver
:Ou vous pouvez le rendre plus général en le modifiant pour accepter le programme récepteur comme argument comme dans la réponse de Gilles:
la source