2010-11-03 2 views
6

J'ai un utilitaire de ligne de commande d'un tiers (il est grand et écrit en Java) que j'ai utilisé pour m'aider à traiter certaines données. Cet utilitaire attend des informations dans un fichier délimité par des lignes, puis envoie les données traitées à STDOUT. Dans mes phases de test, j'ai bien écrit Perl pour créer un fichier complet d'informations à traiter et ensuite envoyer ce fichier à cet utilitaire tiers, mais comme je suis sur le point de mettre ce code en production, je Je préférerais simplement rediriger les données vers cet utilitaire directement au lieu d'écrire ces données dans un fichier, car cela me permettrait d'éviter d'avoir à écrire des informations inutiles sur le disque. Y at-il un moyen de le faire dans unix?Y at-il un moyen de fournir stdin/out au lieu d'un fichier à un programme sous UNIX?

Actuellement j'appelle l'utilitaire comme suit:

bin/someapp do-action --option1 some_value --input some_file

Je voudrais faire quelque chose comme:

bin/someapp do-action --option1 some_value --input $piped_in_data

Est-ce quelque chose comme ça possible sans que je modifier le tiers application?

+0

Il existe une réponse beaucoup plus complète sur StackExchange, voir . – weynhamz

Répondre

10

Vous devriez pouvoir utiliser/dev/stdin:

bin/someapp do-action --option1 some_value --input /dev/stdin 

(Notez que,/dev/stdin est un lien symbolique sur certains systèmes, si votre programme Java ne traite pas, vous pourriez il faut utiliser/dev/fd/0 ou quelque chose de similaire à la place.)

+0

Alors, à quel moment devrais-je envoyer les données à stdin alors? Est-ce que ça l'attendrait après que j'appelle ça? Ou devrais-je le faire immédiatement avant la main? Comment cela fonctionnerait-il exactement? – Eli

+0

Utilisez-le dans un pipeline normal: 'generate_data.pl | bin/someapp faire-action --option1 une-valeur -input/dev/stdin' –

+0

Génial. C'est juste ce que je voulais. – Eli

10

Vous pouvez utiliser "substitution de processus" dans bash pour obtenir quelque chose comme ce que vous voulez.

bin/someapp do-action --option1 some_value --input <(generate_input.sh) 

devrait faire l'affaire. La partie <(list) est la substitution de processus.

+0

Doux! est-il possible d'utiliser un script Perl là-bas? Pour tester, j'ai essayé: echo <(perl -e 'print "yo;"'), mais cela ne semble pas fonctionner. – Eli

+0

essayez à la place: chat - <<(perl -le 'print "yo"') :) – pavel

+0

Ou juste 'cat <(perl quelquechose)'. Le bit <(...) est remplacé par le nom d'un fichier représentant un canal vers les données générées. 'echo' ne sait pas lire des fichiers, mais' cat' le fait. –

2

Un autre chemin, si la technique /dev/stdin ne convient pas pour quelque raison, consiste à utiliser un 'tuyau nommé'.

Si vous

% mkfifo /path/to/file 

alors cela va créer un objet de système de fichiers avec ce nom, qui peut agir comme un conduit entre deux processus. C'est exactement la même chose que ce qui se passe avec un tube normal, sauf que les processus peuvent se référer au tube comme s'il s'agissait d'un fichier normal. Par exemple:

% mkfifo /tmp/my-fifo 
% grep alias ~/.bashrc >/tmp/my-fifo & 
[1] 70134 
% sed 's/alias/wibble/' /tmp/my-fifo 
wibble ls='ls -F' 
.... 
[1] + done  grep alias ~/.bashrc > /tmp/my-fifo 
% 

Ici, la commande grep est en train d'écrire à la FIFO exactement comme si elle était un fichier normal, et il bloque lorsque le tampon du tube nommé remplit. Le processus sed lit à partir du tube (comme s'il s'agissait d'un fichier normal), vidant le tampon comme il le fait.

2

Ce n'est pas si facile./dev/stdin, les canaux nommés et la substitution de processus <() ne sont pas accessibles par un programme de la même manière qu'un fichier. En particulier, il n'est pas possible de fseek(), fsetpos() dans une telle construction, car sa longueur n'est pas connue a priori.

Certaines fonctions comme fopen(), getc(), fread() etc. fonctionneront cependant. Donc, pour la plupart des programmes qui lisent simplement l'entrée ligne par ligne ou caractère par caractère, cela fera l'affaire.

Si votre programme cherche dans un fichier (et peut-être d'autres opérations "plus avancées"), vous devrez malheureusement créer un fichier temporaire.

Questions connexes