קריאת קלט מהמשתמש

קיימות 3 דרכים בהן סקריפט Bash יכול לקבל מידע מהמשתמש: ניתן לקבל פרמטרים בשורת הפקודה, ניתן לקרוא קלט מ STDIN וניתן לקרוא ערך של משתני סביבה. בפרק זה נלמד על שלושת הדרכים, ההבדלים ביניהן ומתי נבחר בכל דרך.

1. קבלת מידע מהמשתמש

קיימות 3 דרכים בהן סקריפט Bash יכול לקבל מידע מהמשתמש שישלוט על פעולתו: הראשונה היא העברת המידע כפרמטרים בשורת הפקודה. כך למשל הפקודה cp מקבלת איזה קובץ להעתיק ולאן:


$ cp /etc/passwd $HOME/copy_of_passwd

דרך ההעברה השניה הינה באמצעות קריאת מידע מ STDIN. פקודות אינטרקטיביות או פילטרים לרוב עובדות באופן כזה. קחו את הפקודה wc לדוגמא:


$ cat /etc/shells | wc

הדרך השלישית הינה משתני סביבה. אלו משתנים מיוחדים אותם מגדירה המעטפת והתוכנית הנקראת בודקת את ערכם וכך משנה את התנהגותה בהתאם. לדוגמא משתנה הסביבה LC_ALL שמשפיע על השפה שתוכניות מציגות פלט למשתמש. נסו את הפקודות הבאות:


$ LC_ALL=fr_FR
$ ls -l

ls זיהה את משתנה הסביבה והתאים את שפת הפלט — צרפתית.
נסקור כעת את שלושת הדרכים להעביר מידע לסקריפט, כיצד ליישם כל אחת ומתי נרצה להשתמש בכל אחת.

2. קלט בשורת הפקודה

האפשרות הנפוצה ביותר להעברת מידע לתוכניות בעולם היוניקס היא פרמטרים בשורת הפקודה. בתוך סקריפט אנו ניגשים לפרמטרי שורת הפקודה באמצעות המשתנים השמורים $1, $2, $3 וכן הלאה. המשתנה השמור $# מכיל את מספר הפרמטרים שהועברו.

ניתן לגשת לכל הפרמטרים באמצעות המשתנים המיוחדים $* ו-$@. ההבדל בין שתי הדרכים מתגלה רק כאשר נשים את המשתנים בתוך מרכאות: במצב זה הראשון ייתן לכם את כל ערכי המשתנים מאוחדים כולם לכדי מילה אחת, והשני ייתן לכם כל ערך משתנה בתוך מילה נפרדת. הנה דוגמא קצרה להמחשת העניין:


#!/usr/bin/env bash
# First script - named create_one.sh

echo Creating files: "$*"
touch "$*"

# Results:
# Create the single file "foo bar"
# ./create_one.sh foo bar
#
# Create the single file "foo bar buz"
# ./create_one.sh "foo bar" buz
#

############################################
#!/usr/bin/env bash
# Second script - named create_all.sh

echo Creating files: "$@"
touch "$@"

# Results:
# Create both files "foo" and "bar"
# ./create_all foo bar
#
# Create 2 files: "foo bar" and "buz"
# ./create_all "foo bar" buz
#

לסיכום יש לציין כי פרמטרים שאנו מקבלים משורת הפקודה יכולים להכיל רווחים. במידה ומכילים תווים מיוחדים, עלינו לשמור עליהם כשאנו מעבירים אותם לתוכניות חיצוניות (למשל touch). המשתנה המיוחד $@ נפרש לרשימת כל הפרמטרים שהועברו בשורת הפקודה. כשנשתמש בו בתוך מרכאות הפריסה תשמור במרכאות על כל פרמטר בנפרד. משתנה זה הוא הדרך המומלצת לגשת לכל הפרמטרים כשורה אחת.

 

3. קריאת STDIN

הדרך השניה לקבל מידע מהמשתמש היא קריאת המידע מ STDIN באמצעות הפקודה read. לרוב אנו נשלב קריאה זו בלולאה כדי לעבוד על קלט ארוך (למשל הפקודות wc, sort, grep, cut וכן הלאה).
הנה דוגמא לסקריפט המבקש את שמכם ומדפיס ברכת שלום (שימו לב למרכאות ששומרות על השאלה. השימוש בהן חיוני בגלל סימן השאלה אחרי המילה you):


#!/usr/bin/env bash
echo “Who are you?”

read NAME

echo Hello, $NAME

יכולת נחמדה של הפקודה read היא האפשרות לחלק את הקלט לשדות. ברירת המחדל להפרדת שדות היא סימן הרווח, בדיוק כמו ש bash מחלק את השורה למילים. הנה למשל פקודת read שתדפיס רק את המילה השניה שקיבלה:


#!/usr/bin/env bash
echo “Who are you?”

read FNAME LNAME REST

echo Hello, $LNAME

כשאתם משתמשים ב read לפצל קלט למילים, זכרו שהמילה הראשונה תכנס למשתנה הראשון, השניה למשתנה השני וכן הלאה, עד המשתנה האחרון שיקבל את כל המשך המשפט.

4. משתני סביבה

הדרך השלישית לשלוט בתוכנית היא באמצעות משתנה סביבה. משתנה סביבה מוגדר ב Shell המפעיל את הסקריפט בשלב כלשהו לפני הפעלת הסקריפט. אנו משתמשים במשתני סביבה לרוב להשפיע על אוסף של סקריפטים לקביעת מאפייני התנהגות של התוכנית.
ראינו כבר את הדוגמא של LC_ALL, משתנה סביבה שמשפיע על השפה שתוכניות יעבדו בהן. משתנה מפורסם נוסף הוא EDITOR, באמצעותו אנו יכולים לציין מהו עורך הטקסט המועדף עלינו. סקריפט שצריך להפעיל עורך טקסט לכל מטרה, יסתכל בדרך כלל במשתנה EDITOR ואם רשום שם ערך יפעיל עורך זה.

אנו מגדירים משתנה סביבה באמצעות מילה הפקודה export, למשל באופן הבא:


export LOGFILE=/tmp/output.log

לאחר מכן בסקריפט ניתן להשתמש במשתנה הסביבה כמו בכל משתנה רגיל:


echo testing > $LOGFILE

משתני סביבה מוכרים בסקריפט שיצר אותם (או ב Shell האינטרקטיבי שיצר אותם) ובכל התוכניות אותן Shell זה מפעיל. כל תוכנית ש Shell מפעיל מקבלת עותק של טבלת משתני הסביבה, ולכן שינוי משתנה סביבה לאחר הפעלת תוכנית לא משפיע על התוכנית הרצה, וגם לא ניתן להשתמש במשתני סביבה כדי לתקשר מידע חזרה מתוך סקריפט פנימי לסקריפט שהפעיל אותו.

מתוך העובדה שמשתני סביבה מוגדרים ״קדימה״, מאוד נוח לתת להם ערכים בקובץ האתחול .bash_profile ולהשתמש בהם להתאמה אישית של תוכניות וסקריפטים. אפשר לשמור בהם העדפות עבור משתמש מסוים וכך כל משתמש יגדיר לעצמו ערכים למשתני הסביבה בקובץ האתחול.

5. תרגול

כתבו תוכניות Bash עבור הסעיפים הבאים:

  1. Write a shell script that takes a file name as input and prints the file backwards
  2. Write a shell script that takes two file names as inputs, and replaces their contents.
  3. Write a shell script that reads a file name from the user, prints its contents and the number of lines in the file.
  4. Write a shell script that takes a Windows file (lines end with \r\n) and converts it to a Unix file (lines end with \n).