2009-09-06 9 views
4

(ce qui est indirectement une partie d'une tâche de travail beaucoup plus)Mise en entrée de l'utilisateur après stdin a été redirigé, dans un script bourne

J'ai quelque chose comme

 
    while read LINE 
    do 
     stuff-done-to-$LINE 
     echo "Enter input:" 
     read INPUT 
     stuff-done-to-$INPUT 
    done < infile 

Je ne peux pas trouver un manière réussie d'utiliser la console/stdin par défaut pour la deuxième lecture, au lieu du stdin redirigé.

Doit être un script bourne pur.

+0

Je dois de préciser le premier bit ... la question/problème est spécifique à ma solution à la tâche, et ne fait pas partie du devoir, mais l'exigence que mon code soit dans Bourne non-étendue est. – Ashton

+0

pur bourne script? Tu veux dire le shell bourne original, pas bash? – skaffman

+0

oui, original bourne shell – Ashton

Répondre

3

Je crois que cela est pris en charge dans le shell Bourne:

exec 3<doc.txt 
while read LINE <&3 
do 
    stuff-done-to-$LINE 
    # the next two lines could be replaced by: read -p "Enter input: " INPUT 
    echo "Enter input:" 
    read INPUT 
    stuff-done-to-$INPUT 
done < infile 

entrée alterne entre le fichier et l'utilisateur. En fait, ce serait un bon moyen d'émettre une série d'invites à partir d'un fichier.

Ceci redirige le fichier "infile" vers le descripteur de fichier numéro 3 à partir duquel le premier read reçoit son entrée. Le descripteur de fichier 0 est stdin, 1 est stdout et 2 est stderr. Vous pouvez utiliser d'autres FD avec eux.

J'ai testé ceci sur Bash and Dash (sur mon système, sh est symétrique de tiret).

Bien sûr cela fonctionne. Voici quelques plus amusant:

exec 3<doc1.txt 
exec 4<doc2.txt 
while read line1 <&3 && read line2 <&4 
do 
    echo "ONE: $line1" 
    echo "TWO: $line2" 
    line1=($line1) # convert to an array 
    line2=($line2) 
    echo "Colors: ${line1[0]} and ${line2[0]}" 
done 

Cette impression alterne le contenu de deux fichiers, en rejetant les lignes supplémentaires de quel que soit le fichier est plus.

ONE: Red first line of doc1 
TWO: Blue first line of doc2 
Colors: Red and Blue 
ONE: Green second line of doc1 
TWO: Yellow second line of doc2 
Colors: Green and Yellow 

Doc1 ne possède que deux lignes. La troisième ligne et les lignes suivantes de doc2 sont supprimées.

+0

Si cela fonctionne, j'ai appris quelque chose de nouveau. Merci. –

+0

Le projet et la question ont disparu depuis longtemps, mais je suis retourné et j'ai vérifié le shell correspondant ... oui, il supportait les descripteurs de fichiers, donc votre premier exemple aurait dû marcher. Le deuxième exemple avec les tableaux échoue ... pas de tableaux dans le shell bourne original. – Ashton

-2

Vous ne pouvez pas. Il n'y a pas de stdin par défaut et de stdin redirigé. Il y a stdin, et ce à quoi il est connecté est soit la console, soit le fichier. La seule chose que vous pouvez faire est de faire un certain temps en utilisant un compteur sur le nombre de lignes de votre fichier. Ensuite, extrayez chaque ligne en utilisant une utilisation intelligente de sed ou tail + head. Vous ne pouvez pas utiliser while read line parce que vous n'auriez aucun moyen de différencier la lecture de la console et la lecture du fichier.

+0

Merci, j'avais peur de tel. Je peux probablement le réécrire différemment, même si tail + head est un peu méchant si le fichier est vraiment gros, et sed n'est pas beaucoup mieux. – Ashton

+0

Ensuite, vous utilisez le mauvais outil –

+1

Oui, vous pouvez - voir ma réponse sur/dev/tty. –

1

Cela devrait à travailler:

for LINE in `cat infile`; do 
    stuff-done-to-$LINE 
    echo "Enter input:" 
    read INPUT 
    stuff-done-to-$INPUT 
done 
+0

+1: oui et non. Cela vous donnera une liste de mots, pas une liste de lignes.Vous devez changer IFS pour entrer votre méthode de travail, ce qui peut avoir des conséquences désastreuses sur le code interne si vous ne faites pas attention et/ou le restaurer. –

2

Vous pouvez lire/écrire dans/dev/TTY terminal de l'utilisateur, ceci est indépendant de ce shell que vous utilisez et si stdin/stdout sont redirigés, vous avez juste besoin:

echo "Enter input:" > /dev/tty 
read INPUT < /dev/tty 
Questions connexes