קריאה עם read מ Pipe ב Bash

23/11/2022

הפקודה read קוראת שורה מהקלט הסטנדרטי, שוברת אותה למילים (עם תו ההפרדה במשתנה IFS) ושומרת את התוצאה למשתנה אחד או יותר שאת שמו היא מקבלת בהפעלה.

לכן הקוד הבא קורא את השורה הראשונה מהקובץ /etc/shells ושומר אותו למשתנה בשם first_line:

read first_line < /etc/shells

והקוד הבא קורא רק את המילה הראשונה מאותו קובץ ושומר אותה למשתנה first_word:

read first_word rest < /etc/shells

קל לשכוח שההתנהגות של read בשילוב | אינה אינטואיטיבית, וזה לא בגלל read. כל פעם שאנחנו מפעילים פקודות בתוך Pipeline, באש פותח תת-מעטפת (Sub Shell) ומבצע את הפקודות בתוכה. הבעיה היא שמשתנים שמוגדרים באותו Sub Shell יימחקו כשה Sub Shell יסתיים, כלומר ביציאה מה Pipeline. הפקודה הזאת לדוגמה לא לוקחת את המילה הראשונה מהפלט של wc /etc/shells לתוך המשתנה lines:

wc /etc/shells | read lines

כלומר היא כן, אבל המשתנה נשמר בתוך Sub Shell ונמחק איך שהשורה נגמרת. בשביל ש read תוכל לשמור משתנה ל Shell הנוכחי שלי היא חייבת להיות מופעלת ממנה, כלומר לא מצד ימין של סימן Pipe. במצב כזה אני צריך להשתמש בפקודת <() כדי להריץ פקודה ולשמור את הפלט שלה לתוך File Handle, ואז בעזרת הפניית קלט רגילה אני יכול להעביר את השורה הראשונה מאותו File Handle ל read:

read lines words chars rest < <(wc /etc/passwd)