أمر القراءة يقوم بتحليل الإدخال متعدد الخطوط

1

ال read الأمر في التعليمات البرمجية أدناه هو تحليل السطر الأول فقط من الإدخال. لكنها تعمل بشكل جيد عندما IFS تم تعيينه إلى فاصلة أو أي رمز آخر غير سطر جديد.

u="*
john
dan"

IFS=$'\n';read -ra q <<< "$u"

for j in "${q[@]}"
do
    echo "drop user $j"
done

الإخراج فقط:

drop user *

ما أتوقعه هو:

drop user *
drop user john
drop user dan

لاحظ أن العنصر الأول في الإدخال هو علامة نجمية. لذلك إذا استخدمت الرمز أدناه للتقسيم ، فسيتم توسيع العلامة النجمية إلى قائمة الملفات في الدليل.

IFS=$'\n'; q=($u); unset IFS;

انتاج:

drop user abc
drop user test.sh
drop user john
drop user dan

ما هو الخطأ في الكود أعلاه؟ كيفية تصحيحها للحصول على الناتج المقصود؟

2 الاجابة

3
افضل جواب

read يقرأ سطر واحد فقط من الإدخال القياسي. إذا كان لديك Bash 4.0 أو أحدث ، يمكنك استخدامه readarray :

readarray -t q <<< "$u"

وبعد ذلك يبدو الصفيف كما يلي:

$ declare -p q
declare -a q=([0]="*" [1]="john" [2]="dan")

readarray (والاسم المستعار mapfile ) الإعدادات الافتراضية لتحديد عناصر المصفوفة بخطوط جديدة ، لذا فإن IFS يمكن إسقاط المهمة. قدم باش 4.4 أ -d خيار استخدام محدد غير السطر الجديد ، ولكن هذا غير مطلوب هنا.

بمجرد أن تكون العناصر في مصفوفة ، يمكنك طباعة أوامرك بمفردك printf بيان على النحو التالي:

printf 'drop user %s\n' "${q[@]}"
:مؤلف
3
افضل جواب

يمكنك فقط القيام بذلك while read عقدة:

u="*
john
dan"
while IFS= read -r user; do
    echo "drop user $user"
done <<< "$u"

انتاج:

drop user *
drop user john
drop user dan
:مؤلف
فوق
قائمة طعام