كيفية التحقق مما إذا كان stdin من المحطة أو أنبوب في نص shell؟
سؤال
أنا أكتب نصًا Posix Shell قد يتلقى أو لا يتلقى مدخلات من stdin كما في foo.sh < test.txt
, ، غير متداخلة.
كيف أتحقق مما إذا كان هناك أي شيء على stdin ، لتجنب التوقف while read -r line...
?
المحلول
إذا حصلت على السؤال بشكل صحيح ، يمكنك تجربة ما يلي:
#!/bin/sh
if [ -t 0 ]; then
echo running interactivelly
else
while read -r line ; do
echo $line
done
fi
نصائح أخرى
للإجابة على السؤال حرفيًا (ولكن ليس ما تريده بالفعل): read -t 0
مهلة ، صفر ثواني.
- هذا شرط سباق ، اعتمادًا على متى يكون الجانب الأيسر جاهزًا لتقديم البيانات. يمكنك تحديد
-t 5
ولكن على نظام السحق حتى هذا مشكلة. read -t
غير موحدة في SUSV3. إنه في BSD SH ، Bash ، Zsh. إنه ليس في KSH أو Dash.
لذلك لا يمكنك استخدام #!/bin/sh ونتوقع الحصول على هذا.
المشكلة الأساسية هي أنه حتى لو لم يكن هناك شيء على Stdin الآن ، فهذا لا يعني أنه لن يكون هناك قريبًا. عادةً ما يترك برنامج "استدعاء أحد" stdin متصلاً بالمحطة/أيا كان ، لذلك لا توجد طريقة لمعرفة ما هو مطلوب.
لذا ، للإجابة على سؤالك حرفيًا ، يمكنك القيام بذلك ، ولكن في الممارسة العملية ، خياراتك هي:
- اختبار إذا كان stdin هو tty:
[ -t 0 ]
- استخدم ArgV للسيطرة على السلوك
يمكنك بسهولة تنفيذ سلوك مشابه كأمر "CAT" ، يتم قراءته من قائمة الملفات المقدمة أو إذا لم يتم توفيرها ، ثم اقرأ من stdin.
على الرغم من أنك قد لا تستخدم هذه الفكرة ، أعتقد أن مقالة Linux Journal هذه ستكون مثيرة للاهتمام بالنسبة لك http://www.linuxjournal.com/content/determine-if-shell-inpt-inpt-coming-terminal-or-pipe
:-)
إذا لم ترغب أبدًا في تشغيل البرنامج النصي بشكل تفاعلي ، اجعله يأخذ ملف الإدخال كمعلمة ، بدلاً من استخدام stdin
. تستخدم بعض البرامج علامة أو اسم ملف خاص للإشارة إلى أنه يجب عليها أخذ المدخلات من الإدخال القياسي بدلاً من ملف ؛ تتيح لك هذه الحالة معالجة خط الأوامر إذا لزم الأمر.
إذا كنت تريد أن يأخذ البرنامج النصي الخاص بك الإدخال القياسي ، فلماذا لا تريد أن تدعه التفاعلي (أو على الأقل يتصرف مثل أدوات Posix الأخرى)؟