Exécution de l'entrée de stdin via le pipeline
J'ai un pipeline de (deux) commandes dont j'ai besoin pour traiter l'entrée du terminal. Avec une seule commande, ce serait facile:
grep "b"
lit depuis stdin, qui est terminal et imprime les lignes contenant b vers stdout (également terminal).
Mais si je pipeline une autre commande, par exemple:
grep "b" | tr 'a' 'a'
il prend toujours l'entrée du terminal, mais ne produit jamais rien. La seule façon de le forcer à faire quoi que ce soit est de démarrer le pipeline avec un fichier comme ceci:
cat "file.txt" | grep "b" | tr 'c' 'a'
Ensuite, il se comporte comme prévu, imprimant les lignes de file.txt contenant b et remplaçant toutes les occurrences de c par a.
Alors, y a-t-il un moyen pour cela de lire stdin au lieu de "file.txt", comme il le fait quand il n'y a qu'une seule commande?
cat - | grep "b" | tr 'c' 'a'
n'a pas fonctionné.
Réponses
Il existe probablement plusieurs façons de procéder. Une manière courante serait d'utiliser "read" pour lire l'entrée d'un stdin. Malheureusement, cela ne gère qu'une ligne à la fois, de sorte qu'elle est normalement encapsulée dans une boucle.
Une autre solution plus hackey pourrait être d'utiliser un tube ou un socket nommé pour «injecter» l'entrée d'un autre TTY ou socket.
Pour certains types de saisie guidée, il peut être approprié d'utiliser "expect" à la place de read.
grep b | tr c a ne lire à partir du terminal. Vous ne voyez pas immédiatement la sortie de l'ensemble du pipeline car il y a un tampon entre grepettr .
Scénarios possibles:
- Si vous écrivez suffisamment de données correspondantes, le tampon finira par se remplir,
trobtiendra une entrée et vous verrez une sortie. Ceci est difficile à obtenir avec une entrée purement manuelle car le tampon peut être relativement grand - Si vous indiquez EOF en appuyant sur Ctrl+ , Dpuis
trobtiendra tout ce qu'il doit faire et vous voir tous les résultats que vous attendez. Il est facile de tester cela manuellement. - Mais si vous abandonnez à la place et appuyez sur Ctrl+, Cvous terminerez le pipeline et perdrez toutes les données se trouvant dans la mémoire tampon. Je suppose que c'est ce que vous avez fait, c'est pourquoi vous pensez que la commande "ne produit jamais rien".
Vous greppouvez ou non prendre en charge l' --line-bufferedoption. Si tel est le cas, la commande suivante imprimera immédiatement les lignes correspondantes:
grep --line-buffered b | tr c a
Vous avez peut-être rencontré le problème avec autre chose que grep. Pour tout programme, essayez ces solutions générales (où grep bn'est qu'un exemple):
stdbuf -o L grep b | tr c a
unbuffer -p grep b | tr c a # probably without echoing input
Notez stdbufet unbuffertravaillez de différentes manières . Je préfère stdbuf.