الحصول على إدخال المستخدم بعد إعادة توجيه stdin ، في نص بورن
سؤال
(هذا جزء غير مباشر من واجب منزلي أكبر بكثير)
لدي شيء مثل
while read LINE do stuff-done-to-$LINE echo "Enter input:" read INPUT stuff-done-to-$INPUT done < infile
لا يمكنني العثور على طريقة ناجحة لاستخدام وحدة التحكم/stdin الافتراضية للقراءة الثانية ، بدلاً من stdin المعاد توجيهها.
يحتاج إلى أن يكون نص بورن النقي.
المحلول
أعتقد أن هذا مدعوم في قذيفة بورن:
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
يتناوب الإدخال بين الملف والمستخدم. في الواقع ، ستكون هذه طريقة رائعة لإصدار سلسلة من المطالبات من ملف.
هذا يعيد توجيه الملف "infile" إلى رقم واصف الملف 3 الذي أوله read
يحصل على مدخلاتها. واصف الملف 0 stdin
, ، 1 هو stdout
و 2 هو stderr
. يمكنك استخدام FDs الأخرى معهم.
لقد اختبرت هذا على Bash و Dash (على نظامي SH متماثل إلى Dash).
بالطبع يعمل. هذا أكثر متعة:
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
هذا يتناوب طباعة محتويات ملفين ، وتجاهل الخطوط الإضافية لأي ملف أطول.
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 لديه فقط سطرين. يتم التخلص من السطر الثالث والخطوط اللاحقة من DOC2.
نصائح أخرى
يمكنك قراءة/كتابة محطة المستخدم من خلال/dev/tty ، وهذا مستقل عن القذيفة التي تستخدمها وما إذا كانت stdin/stdout قد تم إعادة توجيهها ، لذلك تحتاج فقط:
echo "Enter input:" > /dev/tty
read INPUT < /dev/tty
يجب أن يعمل هذا:
for LINE in `cat infile`; do
stuff-done-to-$LINE
echo "Enter input:"
read INPUT
stuff-done-to-$INPUT
done
لا يمكنك. لا يوجد stdin الافتراضي وإعادة توجيه stdin. هناك stdin ، وما هو متصل به هو إما وحدة التحكم ، أو الملف.
الشيء الوحيد الذي يمكنك القيام به هو القيام ببعض الوقت باستخدام عداد على عدد خطوط ملفك. ثم ، استخرج كل سطر باستخدام بعض الاستخدام الذكي لـ SED أو Tail+Head. لا يمكنك استخدام while read line
لأنه لن يكون لديك أي طريقة للتمييز بين القراءة من وحدة التحكم والقراءة من الملف.