J'essaie d'obtenir que bash traite les données de stdin qui sont acheminées, mais pas de chance. Ce que je veux dire, c'est qu'aucun des travaux suivants:
echo "hello world" | test=($(< /dev/stdin)); echo test=$test
test=
echo "hello world" | read test; echo test=$test
test=
echo "hello world" | test=`cat`; echo test=$test
test=
où je veux que la sortie soit test=hello world
. J'ai essayé de mettre des guillemets "" "$test"
qui ne fonctionnent pas non plus.
shopt -s lastpipe
- tldp.org/LDP/abs/html/bashver4.html#LASTPIPEOPTRéponses:
Utilisation
Vous pouvez tromper
read
en acceptant d'un tuyau comme celui-ci:ou même écrire une fonction comme celle-ci:
Mais cela ne sert à rien - vos affectations de variables peuvent ne pas durer! Un pipeline peut générer un sous-shell, où l'environnement est hérité par valeur, et non par référence. C'est pourquoi
read
ne se soucie pas de l'entrée d'un tuyau - c'est indéfini.FYI, http://www.etalabs.net/sh_tricks.html est une collection astucieuse de la cruauté nécessaire pour lutter contre les bizarreries et les incompatibilités des coquilles de bourne, sh.
la source
test=`echo "hello world" | { read test; echo $test; }`
{}
au lieu de()
regrouper ces deux commandes?read
prendre l'entrée du pipe, mais à utiliser la variable dans le même shell qui exécute leread
.bash permission denied
lorsque vous essayez d'utiliser cette solution. Mon cas est tout à fait différent, mais je ne pouvais pas trouver une réponse pour nulle part, ce qui a fonctionné pour moi était (un autre exemple , mais l' utilisation similaire):pip install -U echo $(ls -t *.py | head -1)
. Au cas où quelqu'un aurait un problème similaire et tombe sur cette réponse comme moi.si vous voulez lire beaucoup de données et travailler sur chaque ligne séparément, vous pouvez utiliser quelque chose comme ceci:
si vous voulez diviser les lignes en plusieurs mots, vous pouvez utiliser plusieurs variables à la place de x comme ceci:
alternativement:
Mais dès que vous commencez à vouloir faire quelque chose de vraiment intelligent avec ce genre de chose, vous préférez un langage de script comme perl où vous pouvez essayer quelque chose comme ceci:
Il y a une courbe d'apprentissage assez abrupte avec perl (ou je suppose que n'importe lequel de ces langages) mais vous le trouverez beaucoup plus facile à long terme si vous voulez faire autre chose que le plus simple des scripts. Je recommanderais le livre de recettes Perl et, bien sûr, le langage de programmation Perl de Larry Wall et al.
la source
read
ne lira pas à partir d'un tuyau (ou peut-être le résultat est perdu car le tuyau crée un sous-shell). Vous pouvez cependant utiliser une chaîne ici dans Bash:Mais voir la réponse de @ chepner pour plus d'informations
lastpipe
.la source
Ceci est une autre option
la source
<(..)
a plus$(..)
est que<(..)
renvoie chaque ligne à l'appelant dès que la commande qu'il exécute le rend disponible.$(..)
attend cependant que la commande se termine et génère toutes ses sorties avant de mettre toute sortie à la disposition de l'appelant.Je ne suis pas un expert en Bash, mais je me demande pourquoi cela n'a pas été proposé:
Preuve à un revêtement que cela fonctionne pour moi:
la source
bash
4.2 introduit l'lastpipe
option, qui permet à votre code de fonctionner tel qu'il est écrit, en exécutant la dernière commande dans un pipeline dans le shell actuel, plutôt qu'un sous-shell.la source
La syntaxe d'un canal implicite d'une commande shell dans une variable bash est
ou
Dans vos exemples, vous redirigez des données vers une instruction d'affectation, qui n'attend aucune entrée.
la source
La première tentative a été assez serrée. Cette variation devrait fonctionner:
et la sortie est:
Vous avez besoin d'accolades après le tuyau pour entourer l'affectation à tester et l'écho.
Sans les accolades, l'affectation à tester (après le tube) est dans un shell, et l'écho "test = $ test" est dans un shell séparé qui ne connaît pas cette affectation. C'est pourquoi vous obteniez "test =" dans la sortie au lieu de "test = hello world".
la source
À mes yeux, la meilleure façon de lire depuis stdin dans bash est la suivante, qui vous permet également de travailler sur les lignes avant la fin de l'entrée:
la source
Parce que je tombe amoureux d'elle, je voudrais laisser une note. J'ai trouvé ce fil, car je dois réécrire un ancien script sh pour qu'il soit compatible POSIX. Cela signifie essentiellement pour contourner le problème de pipe / sous-shell introduit par POSIX en réécrivant le code comme ceci:
dans:
Et un code comme celui-ci:
dans:
Mais ce dernier ne se comporte pas de la même manière sur une entrée vide. Avec l'ancienne notation, la boucle while n'est pas entrée sur une entrée vide, mais en notation POSIX c'est le cas! Je pense que c'est dû à la nouvelle ligne avant l'EOF, qui ne peut pas être supprimée. Le code POSIX qui se comporte plus comme l'ancienne notation ressemble à ceci:
Dans la plupart des cas, cela devrait être suffisant. Mais malheureusement, cela ne se comporte toujours pas exactement comme l'ancienne notation si some_command imprime une ligne vide. Dans l'ancienne notation, le corps while est exécuté et dans la notation POSIX, nous nous cassons devant le corps.
Une approche pour résoudre ce problème pourrait ressembler à ceci:
la source
Un script intelligent qui peut à la fois lire les données de PIPE et les arguments de ligne de commande:
Production:
Explication: Lorsqu'un script reçoit des données via un canal, stdin / proc / self / fd / 0 sera un lien symbolique vers un canal.
Sinon, il pointera vers le terminal actuel:
L'
[[ -p
option bash peut vérifier si c'est un tuyau ou non.cat -
lit le destdin
.Si nous utilisons
cat -
quand il n'y en a passtdin
, il attendra pour toujours, c'est pourquoi nous le mettons à l'intérieur de laif
condition.la source
/dev/stdin
ce qui est un lien vers/proc/self/fd/0
Pipeter quelque chose dans une expression impliquant une affectation ne se comporte pas comme ça.
Essayez plutôt:
la source
Le code suivant:
fonctionnera aussi, mais il ouvrira un autre nouveau sous-shell après le tuyau, où
habitude.
J'ai dû désactiver le contrôle des tâches pour utiliser la méthode de chepnars ( j'exécutais cette commande depuis le terminal):
Le manuel de Bash dit :
Remarque: le contrôle des travaux est désactivé par défaut dans un shell non interactif et vous n'avez donc pas besoin de l'
set +m
intérieur d'un script.la source
Je pense que vous essayez d'écrire un script shell qui pourrait recevoir des entrées de stdin. mais pendant que vous essayez de le faire en ligne, vous vous êtes perdu en essayant de créer cette variable test =. Je pense que cela n'a pas beaucoup de sens de le faire en ligne, et c'est pourquoi cela ne fonctionne pas comme vous l'attendez.
J'essayais de réduire
pour obtenir une ligne spécifique à partir de diverses entrées. pour que je puisse taper ...
j'ai donc besoin d'un petit programme shell capable de lire depuis stdin. comme vous le faites.
Voilà.
la source
Que dis-tu de ça:
la source