DanLevy.net

חידון: שליטה ב-Bash וב-Shell

אתה יודע לדבר עם מחשבים? באמת?

בחנו את כישורי כתיבת הסקריפטים ב‑Bash שלכם עם 16 השאלות האלה!

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

חדדו (או הוכיחו) את כישורי כתיבת הסקריפטים ב‑shell שלכם!

איך מגדירים משתנים ב-Bash?

משתנים ב-Bash מוצהרים ללא רווחים סביב סימן =. לדוגמה:

Terminal window
name=Alice

פעולה זו משייכת את הערך "Alice" למשתנה name.

הערה: $name משמש להתייחסות או לקריאת ערך המשתנה.

הוספת רווחים גורמת ל-shell לפרש את הפקודה כתוכנית להרצה, וזה לא מה שאתה רוצה כשאתה מגדיר משתנה.

כמו כן, Bash רגיש לאותיות רישיות, כך ש-name, NAME ו-Name הם משתנים שונים.

לבסוף, משתנים לא יכולים להכיל רווחים או מקפים (-) בשמותיהם. השתמש בקו תחתון (_) או ב-camelCase במקום.

מה ידפיס It's 🔨 Time!?

אני יודע. זה מטורף כמה מהר בריחה הופכת מחרוזות לקשות לפענוח. דמיין בריחה משפות אחרות במחרוזות Bash - עם כל המרכאות, האפוסטרופים וסמלי $ שמבלבלים אותך. 🫠

מרכאות בודדות דורשות בריחה בתוך מחרוזות עם מרכאות בודדות. הרצף של סגירת מרכאה, מרכאה מוברחת, פתיחת מרכאה ('\'') מאפשר פלט של:

It's 🔨 Time!

יש דרכים אחרות לטפל בזה, אבל זו הנפוצה ביותר.

מה הפלט של הפקודה הזו?

Terminal window
echo c{a,b}t

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

כאן, c{a,b}t מתרחבת ל:

cat cbt

עכשיו, מה זה ידפיס?

Terminal window
price="$100"
echo "Cost: $price"

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

מכיוון שאנחנו מריצים את הסקריפט ב-REPL, אין ארגומנטים, ולכן $1 ריק. הטקסט הנותר 00 מודפס כפי שהוא.

כדי להדפיס תו $ מילולי, השתמש בגרשיים בודדים, או ברוח ממנו עם לוכסן אחורי (\):

Terminal window
price="\$100"
echo "Cost: $price"

מה קורה כאן?

Terminal window
str="Bark bark"
echo ${str/bark/meow}

התחביר ${var/pattern/replacement} מחליף את המופע הראשון של pattern ב-replacement. כאן, הפלט הוא:

Bark meow

זה תלוי רישיות. כדי לטפל גם ב-bark וגם ב-Bark, השתמש בתבנית כמו ${var/[Bb]ark/Bark} או נרמל את המחרוזת לפני ההחלפה.

כדי להחליף את כל המופעים, השתמש ב-${var//pattern/replacement}.

כדי להחליף מתחילת המחרוזת, השתמש ב-${var/#pattern/replacement}.

כדי להחליף מסוף המחרוזת, השתמש ב-${var/%pattern/replacement}.

איך אפשר לקבל את האורך של משתנה ב-Bash?

התחביר ${#username} מחזיר את האורך של username.

לדוגמה:

Terminal window
username="@justsml"
echo ${#username} # => 8

למרות ש-wc יעבוד, מבחינה טכנית זה לא חלק מ-Bash.

הכלי wc הוא בדיחה פנימית ישנה שמתייחסת ל”ארון מים” או לשירותים. צוחק! מישהו בכלל קורא את זה?

במציאות, wc היא פקודה עתיקה מ-Posix (ומימי AT&T Unix). זה קיצור של “word count” והיא יכולה לספור שורות, מילים ותווים בקובץ או בזרם קלט.

מה הפלט של הסקריפט אם הקובץ cats.txt קיים?

Terminal window
if [ -e cats.txt]; then
echo "File exists"
else
echo "File does not exist"
fi

האם שמת לב לרווח החסר לפני הסוגר הסוגר?

Bash רגיש מאוד כאן: נדרשים רווחים בתוך ביטויי סוגריים.

בגלל שהרווח החסר גורם לפקודת [ לא לראות סוגר סוגר ], Bash מדפיס אבחון, מתייחס לבדיקה כנכשלת, וממשיך לענף else.

התחביר הנכון הוא:

Terminal window
if [ -e example.txt ]; then
echo "File exists"
else
echo "File does not exist"
fi

הערה: סוגריים כפולים [[ ]] מומלצים לביטויי תנאי. ראה BashFAQ.

איך אפשר להשוות מחרוזות בבאש?

Terminal window
cat1="Rosie"
cat2="Sunflower"
if [ "$cat1" === "$cat2" ]; then
echo "Same cat"
else
echo "Different cats"
fi

עוד שגיאת תחביר של בדיקה!

תפסת את האופרטור === הלא חוקי?

אולי חשבת על JavaScript…

עם [ ... ], באש מדווחת על אבחון והתנאי הוא false, אז ענף else מדפיס Different cats. בבאש, השתמש ב-= או == להשוואות שוויון.

מה הפלט של הסקריפט הזה?

Terminal window
function greet () {
echo "$1"
}
greet Hi Dan

פונקציות ב-Bash יכולות לקבל ארגומנטים. המשתנה $1 מכיל את הארגומנט הראשון שהועבר לפונקציה.

זכרו, $0 הוא שם הסקריפט, $1 הוא הארגומנט הראשון, $2 הוא השני, וכן הלאה. רווחים מפרידים בין ארגומנטים. לכן, greet Hi Dan מעביר את "Hi" כארגומנט הראשון. כדי להעביר את "Hi Dan" כארגומנט יחיד, יש להקיף אותו במרכאות: greet "Hi Dan".

איזה אופרטור מחבר את הפלט של פקודה אחת לקלט של הפקודה הבאה?

אופרטור הצינור | מחבר את הפלט של פקודה אחת לקלט של פקודה אחרת. לדוגמה:

Terminal window
echo "Mr. Levy 👨🏻‍🔬" | wc -m
# => 14

איך עובדת מתמטיקה בבאש?

התחביר (( )) מבצע חישובי מספרים שלמים בבאש.

ניתן להשתמש בו לחישובים פשוטים:

Terminal window
((result = 2 + 2))
echo $result # => 4

או לביטויים תנאיים:

Terminal window
if (( 2 > 1 )); then
echo "2 is greater than 1"
fi

לחישובי נקודה צפה, שקול להשתמש ב-bc או awk.

איזו מהפקודות הבאות מכפילה נכון את 10 ב-0.5 ומדפיסה 5?

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

Bash (אולי באופן מפתיע) חסר תמיכה מובנית בחישוב נקודה צפה.

הפתרון הנפוץ ביותר הוא להשתמש בכלי GNU bc או awk.

מה עושה ה-: בסקריפט הזה?

Terminal window
rosie="Bad cat, good cat"
echo ${rosie:9}

התחביר ${var:offset} מחלץ תת-מחרוזת החל מ-offset. כאן, הפלט הוא:

good cat

כדי לחלץ תת-מחרוזת באורך מסוים, השתמש ב-${var:offset:length}.

כדי לחלץ מסוף המחרוזת, השתמש ב-${var: -offset}. (שים לב לרווח לפני ה--!)

מהי מילת המפתח שאינה ❌ לולאה בבאש?

each אינה מילת מפתח ללולאה בבאש. מילות המפתח העיקריות ללולאות הן for, while, ו-until.

למרות ש-do אינה מילת מפתח ללולאה מבחינה טכנית, היא חלק מרכזי בתחביר הלולאה.

איזו אפשרות תבצע את הפקודה ls -l ותחזיר את הפלט?

התחביר $(ls -l) מבצע את הפקודה בתוך הסוגריים ומחליף את הפלט. לדוגמה:

Terminal window
echo "Today is $(date +%F)"
# => Today is 2029-12-31

האפשרות הראשונה משתמשת בגרשיים בודדים ', לא בגרשיים אחוריים. זה מונע הרחבה, כך ש-'$(date +%F)' פשוט ידפיס את המחרוזת המילולית $(date +%F).

בעוד שעדיין נתמך שימוש בגרשיים אחוריים (`ls -l`) לביצוע פקודות, לאחרונה זה הפך למעין אנטי-תבנית (בהקשרים מסוימים). רוב האנשים ממליצים להשתמש ב-$(command) לקריאות טובה יותר ועקביות עם מעטפות וגרסאות שונות.

סוגריים מסולסלים ${} משמשים להרחבת משתנים, לא להחלפת פקודה.

התו % אינו משמש להחלפת פקודה.

איזה אופרטור משמש לשילוב פלט השגיאה לתוך הפלט הסטנדרטי?

האופרטור 2>&1 מפנה את פלט השגיאה הסטנדרטי (תיאור קובץ 2) לפלט הסטנדרטי (תיאור קובץ 1). זה שימושי ללכידת הודעות שגיאה באותו זרם פלט כמו הפלט הרגיל.

האופרטור 1>&2 מפנה את הפלט הסטנדרטי לשגיאה הסטנדרטית, אך השאלה שאלה כיצד להפנות שגיאה סטנדרטית לפלט סטנדרטי.

למידע נוסף על מה שקורה מתחת למכסה המנוע, בדקו את שאלות נפוצות מצוינות של גרג על הפנייה.

כמו כן, תודה למשתמש Reddit u/OneTurnMore על הצעות לשיפור הנוסח.

האם החידון שלי על Bash הותיר אותך הרוס?

ספר לי בתגובות למטה!

קריאה נוספת

רענן את כישורי ה-Bash שלך בעזרת המשאבים הבאים: