590 likes | 713 Views
תרגול מס' 6. תכניות סטנדרטיות ב UNIX שרשור פקודות באמצעות Pipeline עבודה ב- bash. Pipeline. הרכבת פקודות Pipeline. הרכבת פקודות. נניח שברצוננו להדפיס את התוכן של תיקיה המכילה הרבה קבצים לא נוכל במצב זה לראות את כל הקבצים נוכל להשתמש בהפנית
E N D
תרגול מס' 6 תכניות סטנדרטיות ב UNIX שרשור פקודות באמצעות Pipeline עבודה ב-bash
Pipeline הרכבת פקודות Pipeline מבוא לתכנות מערכות - 234122
הרכבת פקודות • נניח שברצוננו להדפיס את התוכן של תיקיה המכילה הרבה קבצים • לא נוכל במצב זה לראות את כל הקבצים • נוכל להשתמש בהפנית פלט הפקודה ls לקובץ זמני ולאחר מכן שימוש ב-more: > ls -l > tmp > more < tmp > rmtmp מבוא לתכנות מערכות - 234122
Pipeline • כדי לחסוך את הבלגן שבטיפול בקבצים זמניים ניתן להשתמש ב-pipeline המחבר את הפלט של פקודה אחת לקלט של פקודה שניה ישירות • כדי לחבר שתי פקודות כך נרשום אותן אחת אחרי השניה כאשר ביניהן מפריד התו ‘|’ • על מנת לראות בשלבים את התוכן של תיקיה גדולה נוכל לרשום כעת: > ls -l | more • ניתן לשלב מספר תכניות בבת אחת: > command1| command2| command3 command1 command2 command3 stdout stdin stdout stdin מבוא לתכנות מערכות - 234122
Pipeline - סיכום • ניתן להשתמש בתו ‘|’ כדי לחבר את הפלט של תכנית א' עם הקלט של תכנית ב' • בעזרת pipeline נוכל להרכיב פקודות מורכבות בעבודה בטרמינל מתכניות פשוטות מבוא לתכנות מערכות - 234122
עבודה ב-Bash מהו bash? תכונות מתקדמות של bash עבודת ה-bash מבוא לתכנות מערכות - 234122
Shell • Shell (קליפה) הוא כינוי לתוכנה המקשרת בין המשתמש לבין גרעין מערכת ההפעלה • בדרך כלל המונח בשימוש עבור shell טקסטואלי • עבודת ה-Shell מתבצעת על ידי קבלת פקודה מהמשתמש, ביצוע החלפות טקסט בפקודה בהתאם לתכונות ה-Shell ולבסוף שליחת הפקודה המעובדת למערכת ההפעלה • דוגמאות ל-shell: • Bash(ברירת המחדל ברוב הפצות הלינוקס) • C-Shell(ברירת המחדל עבור מחשב ה stud) • Powershell(shell מתקדם עבור windows) • בקורס זה נלמד את Bash • מלבד מנשק בסיסי לביצוע פקודות ה-Shellמקל עלינו את העבודה בעזרת תכונות מתקדמות, לדוגמה ההשלמה האוטומטית המתבצעת ע"י לחיצה על Tab • ה-Shell יאפשר לנו להגדיר קיצורים, לחזורעל פקודות, להתייחס למספר קבצים בנוחות ולהגדיר משתניםאשר נוכל להשתמש בהם בפקודות מבוא לתכנות מערכות - 234122
החלפת ה-Shell • ניתן להשתמש בפקודה הבאה כדי לקבל את שם ה-Shell הנוכחי ב-Unix > echo $0 tcsh • במחשבים בהם Bash אינה Shell ברירת המחדל (כמו בשרת ה-stud לדוגמה), ניתןלהשתמש בפקודה chsh (change shell)כדי לשנות את ברירת המחדל: • חשוב להקפיד לכתוב את שם ה-Shell (הייחוס אליו) נכון, אחרת החשבון נהרס • מלבד החלפת ה-Shell המשמש כברירת מחדל, ניתן תמיד להריץ Shell אחר כמו כל פקודה אחרת > chsh Changing shell for mtm. old shell: /bin/tcsh New shell: /bin/bash Shell will be changed for mtm in approximately 5 minutes > מבוא לתכנות מערכות - 234122
הפקודה echo • במקרים רבים נרצה להדפיס לפלט מחרוזת, לשם כך ניתן להשתמש בפקודה echo • הפקודה echoמדפיסה את הפרמטרים שקיבלה > echo [-n] [words] • -n: מדפיס ללא ירידת שורה > echo Hello world! Hello world! > > echo –n Hello world! Hello world! > מבוא לתכנות מערכות - 234122
נתינת כינויים לפקודות - alias • הפקודה alias מאפשרת להגדיר קיצורים ב-Shell > alias <new name>="<command + parameters>" • אסור לשים רווחים בסמוך לתו '=' • לאחר הרצת הפקודה נוכל לרשום את הפקודה <new name> כקיצור לפקודה <command> עם הפרמטרים שהוספנו. • ה-Shell יבדוק בשלב עיבור הפקודה האם המילה הראשונה היא alias ואם כן יבצע החלפה מתאימה • כדי לבטל alias ניתןלהשתמש בפקודה unalias <alias> < alias ll="ls –l" > ll -rw-r--r-- 1 user staff 0 Nov 13 15:14 a.c > alias cdex2="cd ~/mtm/ex2" > cdex2 > alias GCC="gcc -std=c99 -Wall -Werror -pednatic-errors" > GCC hello.c -o hello > unalias GCC > GCC hello.c -o hello -bash:GCC: Command not found. מבוא לתכנות מערכות - 234122
Filename Expansion • ניתן לרשום בפקודה תבנית המתייחסת למספר קבצים. במקרה זה bash יחליף את מחרוזת התבנית בפקודה ברשימת הקבצים המתאימים לתבנית • הסימן * מתאים למחרוזת כלשהי (כולל ריקה) • הסימן ? מתאים לתו כלשהו יחיד • ניתן להתייחס למספר תווים אפשריים על ידי שימוש ב-[ ] • ניתן לרשום את התווים האפשרייםאחד אחרי השני במפורש • ניתן לרשום טווח של תווים, למשל a-z • ניתן להתייחס למספר מחרוזות שונות בעזרת { } • אפשרות זו אינה מתחשבת בקבצים קיימים <ls axb.c a3b.c cab.txt a4b.txt > echo files: * files: axb.ca3b.c cab.txt a4b.txt > echo The source files are *.c The source files are axb.c a3b.c > echo a[0-9]b.* a3b.c a4b.txt > echo a3b.{c,txt} a3b.c a3b.txt מבוא לתכנות מערכות - 234122
משתנים • ניתן להציב ערך למשתנה ב-bash על ידי השמה ישירה > <varname>=<value> • אין צורך להכריז על משתנים ב- bash, לאחר ביצוע השמה למשתנה הוא מוגדר אוטומטית • ניתן להחליףערך של משתנה על ידי השמה נוספת • אסור לשים רווח בין סימן ההשמה לשם המשתנה והערך • אם יהיה כזה רווח ה-Shell ינסה להריץ פקודה ששמה כשם המשתנה • ניתן לקרוא משתנים על ידי שימוש באופרטור $, למשל: > echo $<varname> • השימוש במשתנה הוא פשוט החלפת הקריאה למשתנה בערך השמור בו מבוא לתכנות מערכות - 234122
משתנים • ניתן לבטל הגדרה של משתנה על ידי הפקודה unset <varname> < unset my_variable • בדרך כלל אין צורך בכך • אם מנסים לקרוא משתנה שאינו מוגדר אז לא מודפס כלום • ניתן להשתמש ב-{} כדי לסמן מהו שם המשתנה לאופרטור $ • מועיל כאשר השימוש במשתנה צמוד למחרוזת נוספת > a=Hell > echo $ao > echo ${a}o Hello מבוא לתכנות מערכות - 234122
משתנים - מערכים • ניתן לשמור במשתנה יחיד מערךשל מחרוזות על ידי שימוש בסוגריים > arr=(1 2 3) • קריאת משתנה שקולה לקריאת האיבר הראשון (אינדקס 0) מהרשימה > echo $arr1 • קריאת כל המערך ניתנת מתבצעת על ידי שימוש ב-[*] ובסוגריים מסולסלים: > echo ${arr[*]{1 2 3 > echo $arr[*]1[*] • ניתן לגשת לאיבר יחיד בעזרת אופרטור [ ] • ניתן להוסיף איברים חדשים למערך בשיטה זו > arr[3] = 4> echo ${arr[*]{1 2 3 4 מבוא לתכנות מערכות - 234122
משתנים - מערכים • ניתן לקבל את מספר האיברים במערך בעזרת {#<varname>[*]}$: > echo ${#arr[*]}4 • ניתן לגשת לתחומים של איברים במערך במערך > echo A:${arr[*]:0:2} A:1 2 > echo B:${arr[*]:1} B:2 3 4 > echo C:${arr[*]:2:1}C:3 • המספר הראשון מציין את אינדקס ההתחלה של התחום • המספר השני מציין את מספר האיסרים בתחום • אם הוא אינו מופיע יודפסו כל האיברים החל מהאינדקס המבוקש מבוא לתכנות מערכות - 234122
משתנים - מחרוזות • ניתן לשמור מחרוזות המכילות רווחים בעזרת שימוש בגרשיים כפולים > list=(Matam "Hello world" 17) > echo ${#list[*]} : ${list[*]} 3 : Matam Hello world 17 > echo ${list[1]} Hello world • קריאת משתנה שערכו מכיל רווחים תגרום לאיבוד הרווחים המדויקים שהיו בין המילים קודם לכן > str=" Very crazy spaces " > echo $str Very crazy spaces מבוא לתכנות מערכות - 234122
משתנים - מחרוזות • ניתן להשתמש בגרשיים כפולים כדי לשמור על הרווחים בזמן ההחלפה > echo "$str" Very crazy spaces • ניתן לקבל את מספר התווים במשתנה ע"י שימוש ב-#, בדומה לקבלת אורכו של מערך > echo ${#str} 29 מבוא לתכנות מערכות - 234122
משתנים - מערכים • ניתן להתייחס למשתנה רגיל כאל רשימה בעלת איבר יחיד > a=Hello > echo ${a[0]} Hello > str="Hello world" > echo ${str[1]} > list=(Hello world) > echo ${list[1]} world • בעזרת unset נוכל לבטל את הרשימה או איבר אחד מתוך הרשימה > unset list[1] > echo ${list[*]}Hello מבוא לתכנות מערכות - 234122
משתנים - חישוב ביטויים • בניגוד לשפת C, למשתנים ב-bash אין טיפוס. כל המשתנים הם מסוג מערך של מחרוזות • ניתן להחליף ביטוי אריתמטי בערכו על ידי $((<expression>)) • הערך המספרי של המחרוזות ישמש בחישוב הביטוי • משתנים יוחלפו בערכם (גם ללא $) • אם אחד הארגומנטים אינו מספר, ערכו יהיה 0 בחישוב • משתנה שאינו מוגדר, או ערכו אינו מספר יחושב כ-0 > echo $((3 + 4)) 7 > n=$((3 * 7 + 4)) > echo $n 25 > a=5 > b=7 > sum=$(($a + $b)) > echo $sum 12 > echo $(( Hello )) 0 > a=4 > echo $(( 2 + a )) 6 > str="Hello world!" > num=17 > echo $(( $str * $num )) 0 מבוא לתכנות מערכות - 234122
משתנים - פעולות חשבוניות • ניתן לבצע את פעולות חשבוניות שונות בדומה לשפת C: • פעולות חשבוניות פשוטות: +, -, * ו-/ • השמות: = • הגדלות והקטנות: =+, =-, -- ו-++ • ניתן לבצע פעולות חשבוניות רק על מספרים שלמים • ניתן להשתמש גם בפקודה letכדי לבצע פעולה חשבונית • נוח כאשר רוצים להשתמש ב-++ ואין צורך בערך ההחזרה > let n=3+4 > let n++ > echo $n 8 > $((n++))-bash: 9: command not found Bash מנסה לבצע פקודה בשם "9" ונכשל מבוא לתכנות מערכות - 234122
היסטוריה • Bash שומר את הפקודות האחרונות שהתבצעו ומאפשר ביצוען מחדש • הדרך הכי פשוטה לגשת להיסטוריה היא על ידי שימוש ב-↑ ו-↓ • ניתן לראות את הפקודות האחרונות שבוצעו על ידי הפקודה history • ניתן לבצע את האחרונה על ידי !! • ניתן לבצע את פקודה מספר על ידי ! • ניתן לבצע את הפקודה האחרונה שהתחילהב-<string> על ידי !<string> • ניתן לבצע את הפקודה האחרונה שמכילה<string> על ידי !?<string> • אפשר להחליף str1במחרוזת str2בפקודה האחרונה ע"י ^str1^str2^ . > history 1 17:20 let a = 3 2 17:21 let b = 4 3 17:22 @ n = $b + $a 4 17:24 echo $n 5 17:28 history > !4 echo $n 7 > !! echo $n 7 > !let let b = 4 > ls/it/is/avery/long/path > ^ls^cat^ cat /it/is/avery/long/path החלפות המתבצעות בגלל גישה להיסטוריה מודפסות בזמן ביצוען ולפני ביצוע הפקודה מבוא לתכנות מערכות - 234122
Command Substitution • ניתן "לשרשר" פקודות על ידי שימוש בגרשיים הפוכים ` • באנגלית: backticks או backquotes • Bash יבצע תחילה את הפקודה בתוך ` ` ויחליף אותה בפלט שלה > echo The length of $str is `echo -n $str | wc -c` The length of Hello is 5 > grep –c cow `cat farms_list.txt` farm1:3 farm2:2 > set a ="there are `ls | wc -l` files in `pwd` " > echo $a there are 662 files in /usr/bin farms_list.txt farm1 farm2 מבוא לתכנות מערכות - 234122
סוגי גרשיים • גרשיים כפולים, " ", משמשים לשמירה על רווחים • משתמשים ב-" " כאשר יש צורך לשמור מחרוזות שלמות במדויק > sentence="The dingo ate your baby" • בתוך גרשיים אלו לא מתבצעות החלפות של תבניות בשמות הקבצים המתאימים > echo "*.c" : *.c *.c : main.capp.chello.c • גרשיים בודדים ' ', מונעים את כל ההחלפות בתחומם > echo lets make some '$$' lets make some $$ • גרשיים הפוכים (backticks) מבצעים command substitution מבוא לתכנות מערכות - 234122
עבודת ה-shell • עבודת ה-Shell מתבצעת בלולאה: • הצגת prompt • המתנה לפקודה • עיבוד הפקודה עד לקבלת פקודה פשוטה • ביצוע הפקודה • לשם כך Bash מנהל מבני נתונים פנימיים אשר שומרים את ההיסטוריה, המשתנים וה-aliasesשהוגדרו • הטיפול בפקודה מתבצע בשלושה שלבים עיקריים • ניתוח הפקודה: הפקודה מופרדת למילים על פי רווחים וטאבים. התווים |,< ו-> מפרידים בין פקודות • עיבוד הפקודה:ביצוע החלפות מחרוזות הפקודה עד לקבלת פקודה פשוטה • ביצוע הפקודה: שליחת הפקודה הפשוטה שהתקבלה לביצוע על ידי מערכת ההפעלה מבוא לתכנות מערכות - 234122
עיבוד הפקודה • בשלב זה מבצע bash החלפות במחרוזת הפקודה עד לקבלת פקודה פשוטה: • אם הפקודה מכילה שימוש בפקודות קודמות (ע"י שימוש בסימן !) מתבצעת החלפה מההיסטוריה ומודפסת שורת הפקודה שנבחרה מההיסטוריה • אם המילה הראשונה בפקודה הינה aliasמתבצעת החלפה לפי ה-alias המוגדר • החלפת ביטויים המתחילים ב-$ בערכי המשתנים המתאימים • החלפת תבניות של שמות קבצים ברשימת הקבצים המתאימה • החלפת פקודות המופיעות בתוך גרשיים הפוכים בתוצאת הפקודה מבוא לתכנות מערכות - 234122
ביצוע הפקודה • לאחר שהתקבלה פקודה סופית על bash להפעיל את הפקודה המתאימה, הפקודות מתחלקות שני סוגים: • פקודות פנימיות של ה-Shell, למשל cd, let, unset,... • פקודות חיצוניות - שמות קבצי הרצה, למשל ls, gcc, cat, sort... • אם שם הפקודה מתאים לפקודה פנימית היא תיבחר • אחרת ה-Shell יחפש בכל התיקיות המופיעות במשתנה pathקובץ הרצה בשם המתאים, • אם נרצה לאפשר ל-Shell להריץ תכניות מהתיקיה הנוכחית ללא שימוש ב-‘.’ניתן להוסיף את התיקיה הנוכחית ל-PATH. • התיקיות מופרדות ע"י סימן ":" . • ניתן להשתמש בפקודה whichכדי לגלותאיזו תכנית תופעל עבור שם פקודה מסוים > PATH=${PATH[*]}:. > hello Hello world! > which hello ./hello > which gcc /usr/bin/gcc < which cd Which: no cd in (…content of PATH…) מבוא לתכנות מערכות - 234122
עבודה ב-Bash - סיכום • ל-Bash מגוון תוכנות מתקדמות המאפשרות למשתמש מתקדם לבצע פעולות מסובכות בקלות • ניתן להתייחס למספר קבצים בבת אחת על ידי שימוש בתבניות • ניתן להגדיר כינויים לפקודות ופרמטרים שכיחים בעזרת alias • ניתן לקרוא לפקודות שהתבצעו בעבר הקרוב בעזרת ההיסטוריה • ניתן לשמור ערכים במשתנים ולנצלם לפקודות ב-Bash • כל המשתנים ב-bash הם מסוג רשימות של מחרוזות • ניתן להשתמש ב-` ` כדי לבצע החלפת פקודה בפלט שלה בשורות פקודה ב- bash • כל התכונות של bash מבוצעות על ידי החלפת מחרוזות פשוטה בשלב עיבוד הפקודה מבוא לתכנות מערכות - 234122
תסריטים הרצת תסריטים מבני בקרה ב-bash דוגמאות השוואה בין C ו-bash מבוא לתכנות מערכות - 234122
אוטומטיזציה • נניח (מקרה היפותטי לחלוטין) שברשותנו קבצי בדיקה ופלט לתכנית שלנו וברצוננו לבדוק את נכונות התכנית מול קבצים אלו • צריך לכתוב 3 פקודות לכל בדיקה • גם עם שימוש במנגנון ההיסטוריה הרצת הבדיקותמעיקה ולוקחת הרבה זמן מיותר • הפתרון:אוטומטיזציהשל הרצת הפקודות. ניצור קובץ אשר יכיל "תסריט" לפיו יורצו כל הפקודות לפי הסדר > mtm_rentals< test1.in > tmpout 2> tmperr > diff expout1 tmpout > diff experr1 tmperr מבוא לתכנות מערכות - 234122
הרצת תסריט בעזרתsource • ניתן להריץ קובץ המכיל פקודות Bash (להלן תסריט - script) על ידי הפקודה source • הפקודות יבוצעו ב-Shell הנוכחי כאילו נכתבו בשורת הפקודה אחת אחרי השניה > source run_tests Running test 1 Running test 2 Running test 3 run_tests echo Running test 1 mtm_rentals< test1.in > tmpout 2> tmperr diff expout1 tmpout diff experr1 tmperr echo Running test 2 mtm_rentals< test2.in > tmpout 2> tmperr diff expout2 tmpout diff experr2 tmperr echo Running test 3 mtm_rentals< test3.in > tmpout 2> tmperr diff expout3 tmpout diff experr3 tmperr מבוא לתכנות מערכות - 234122
תסריטי אתחול • בהתחברות של משתמש למערכת מורץ התסריט .login אשר בתיקית הבית של המשתמש • בפתיחת Shell חדש של Bash מורץ התסריט .bashrc • הרצות תסריטי האתחול מתבצעות באמצעות source, ולכן הן משפיעות על מצב ה-Shell .bashrc .login PATH=$PATH:. alias ll="ls -l" alias cdex2="cd ~mtm/public/1011a/ex2" alias GCC="gcc -std=c99 -Wall \ -pedantic-errors -Werror" # welcome message echo ------ Welcome `whoami` !-------- echo You are in `pwd` directory of \ `hostname` echo OS is `uname -s` # echo disk usage is `du -sh | cut -f1` echo `who | wc -l` users are logged in echo Today is `date` מבוא לתכנות מערכות - 234122
הרצת תסריט כקובץ הרצה • ניתן להריץ תסריט כפקודה: • בתחילת התסריט יש להוסיף את השורה #!/bin/bash • #! מסמן ל-Unix שהשורה הראשונה בקובץ מגדירה את התכנית לביצוע שאר הפקודות בקובץ • /bin/bashהוא שם התכנית לביצוע הפקודות, במקרה שלנו Bash • בנוסף יש להוסיף הרשאת ריצה לקובץ • כעת ניתן להריץ את התסריט כמו תכנית רגילה • בניגוד להרצה באמצעות פקודת source התסריט יבוצע בתהליך Shell חדש אשר יסתיים בסוף ריצת התסריט מבוא לתכנות מערכות - 234122
הרצת תסריט כקובץ הרצה • נמיר את תסריט הרצת הבדיקות שלנו לקובץ הרצה: • בעיה חדשה: התסריטמתחיללהסתבך, הוספת בדיקות נוספותמשכפלת קוד בתסריט ולא נוחה (ייתכנו אלפי בדיקות) • פתרון: נשתמש במבני בקרה (תנאים ולולאות) בדומה לשפת C > chmoda+xrun_tests > ./run_tests Running test 1 Running test 2 Running test 3 run_tests #!/bin/bash echo Running test 1 mtm_rentals < test1.in > tmpout 2> tmperr diff expout1 tmpout diff experr1 tmperr echo Running test 2 mtm_rentals < test2.in > tmpout 2> tmperr diff expout2 tmpout diff experr2 tmperr echo Running test 3 mtm_rentals < test3.in > tmpout 2> tmperr diff expout3 tmpout diff experr3 tmperr מבוא לתכנות מערכות - 234122
מבני בקרה • Bash מאפשרת שימוש במבני בקרה (למשל whileו-if) בתסריטים ובשורת הפקודה • מבני הבקרה משתמשים בתנאיםבדומה למבני הבקרה שבשפת C • השוואת ערכי מספרים • השוואת מחרוזות • ועוד... • נעבור על מספר מבני בקרהותנאים שימושיים > for ((i = 1; $i < 10; i++ )); do > if (($i % 3 == 0)); then > echo 3 divides $i > fi > done 3 divides 3 3 divides 6 3 divides 9 מבוא לתכנות מערכות - 234122
while • ניתן ליצור לולאות whileב-bash: while <expression>; do<command1><command2>...done • הפקודות בגוף הלולאה יבוצעו כל עוד <expression> ממשיך להתקיים • לולאות while כמו שאר מבני הבקרה ניתנות לביצוע ישירותמהטרמינל > i=1 > while ((i <= 3)); do > echo $i > let i++ > done 1 2 3 run_tests > ./run_tests Running test 1 Running test 2 Running test 3 #!/bin/bash i=1 while ((i <= 3)); do echo Running test $i mtm_rentals< test${i}.in \ > tmpout 2> tmperr diff expout${i} tmpout diff experr${i} tmperr let i++ done מבוא לתכנות מערכות - 234122
for • שימוש נוסף ב-for הוא מעבר על על איברי המערך: for <varname> in <array> ; do <command1> <command2> ...done • <varname> הוא שם המשתנה שיכיל בכל פעם איבר מהרשימה • <array>היא רשימה של מחרוזות • העדיפו להשתמש בשיטה זו על פני שימוש מפורש באינדקסים מבוא לתכנות מערכות - 234122
for • לולאת for משמשת בדומה לשפת C למעבר נוח יותר על תחום מספרים > ./run_tests Running test1.in Running test2.in Running test3.in run_tests #!/bin/bash for ((i = 1; i <= 3; i++)); do echo Running test$i mtm_rentals < test${i}.in > tmpout 2> tmperr diff expout$itmpout diff experr$itmperr done מבוא לתכנות מערכות - 234122
if • ניתן להגדיר ב-bash משפטי תנאי בשתי גרסאות if <expression>; then <command1> <command2> ... fi • ניתן להוסיף else ופקודות אשר יתבצעו אם התנאי אינו מתקיים if<expression>; then <commands> else <commands>fi > i=1 > if (( $i> 0 )); then > echo POSITIVE > else > echo NEGATIVE > fi POSITIVE מבוא לתכנות מערכות - 234122
ביטויים אפשריים ב-if ו-while • קיימות מספר אפשרויות לכתיבת התנאים בלולאות ומשפטי תנאי • ניתן לרשום תנאים בתוך [[ ]]: • האופרטורים ==, > ו-< משווים מחרוזות (לפי סדר לקסיקוגרפי) • ניתן לבצע השוואת על ערכי מספרים בעזרת דגלים כגון -eq, -gt, -le • חשוב להקפיד על תו הרווח בין הסוגריים לתוכן התנאי כדי למנוע שגיאות ב-bash > str1=Hello > if [[ $str1 == Hello ]]; then echo true; fi true > if [[ hello == Hello ]]; then echo true; fi > if [[ 11 < 7 ]]; then echo true; fi true > if [[ 11 -le 7 ]]; then echo true; fi > if [[ 11 -eq 11 ]]; then echo true; fi true > if [[ 0 -eq Hello ]]; then echo true; fi true זו אינה השוואת ערכים מספריים עבור ערך שאינו מייצג מספר משתמשים ב-0 לחישוב מבוא לתכנות מערכות - 234122
ביטויים אפשריים ב-if ו-while • בתוך [[ ]] ניתן להשתמש בתנאים מועילים נוספים, למשל: • התנאי -f <filename> בודק האם קיים קובץ בשם <filename> • התנאי -d <dirname> בודק האם קיימת תיקייה בשם <dirname> • ניתן לבדוק תנאים מורכבים יותר: • ניתן להשתמש באופרטורים &&, ||, ו-! כמו בשפת C • הקפידו להשאיר רווח אחרי ! כדי להימנע משגיאות בגלל מנגנון ההיסטוריה • ניתן להשתמש בסוגריים כדי לקבוע את הקדימויות > if [[ -f a.txt ]]; then echo file exists; fi > cat > a.txt Hello world! > if [[ -f a.txt ]]; then echo file exists; fi file exists > mkdirmtm > if [[ ! (-f b.txt && -d mtm) ]]; then echo yes; fi yes מבוא לתכנות מערכות - 234122
התאמת מחרוזות • בתוך תנאי מהצורה [[ ]], האופרטור = מאפשר התאמת מחרוזת לתבנית • הארגומנט השמאלי הוא מחרוזת רגילה • הארגומנט הימני הוא תבנית אשר יכולה לכלול את הסימנים *, ? ו-[ ] כמו שתואר עבור תבניות של שמות קבצים • האופרטור =! הוא השלילה של אופרטור ההתאמה = • שימו לב שהמשמעות של = ו-== שונה > end_with_z="some string with z" > if [[ "$end_with_z" = *[zZ] ]]; then echo match; fi match > if [[ "this string start with t" = t* ]]; then echo true; fi true > if [[ "this string doesn't start with t" = [^t]* ]]; then echo true; fi > file=test4.in > if [[ $file = test*.in]]; then echo test file; fi test file > if [[ "string doesn't start with t" != t* ]]; then echo true; fi true מבוא לתכנות מערכות - 234122
ביטויים אפשריים ב-if ו-while • ניתן להגדיר תנאי בתוך (()) • בתוך (()) האופרטורים ==, =!, > ו- < מתייחסים לערכים מספריים • אין צורך לרשום $ לפני שם משתנה • ניתן לבצע פעולות חשבוניות • תנאים המוגדרים בעזרת (())מתנהגים כמו ביצוע פעולות חשבוניות בעזרת (())$ > if (( 11 < 7 )); then echo true; fi > i=5 > if (( i >= 0 && i <= 10 )); then echo true; fi true > if [[ 11 -eq 11 ]]; then echo true; fi true > if (( 0 == Hello )); then echo true; fi true > if (( ++i == 6 )); then echo true; fi true > if (( ++i == 6 )); then echo true; fi מבוא לתכנות מערכות - 234122
העברת פרמטרים בשורת הפקודה • כמו ב-C ניתן לגשת לפרמטרים המועברים בשורת הפקודה לתסריט • הפרמטר ה-n לתסריט נקרא פשוט n, וניתן לקרוא אותו על ידי $n • $* יוחלף ברשימת כל הארגומנטים לתסריט • אם ייתכנו רווחים בתוך הארגומנטים ניתן להשתמש ב-"$@" כדי לשמור על מספר האגומנטים הנכון • $0 יוחלף בשם התסריט • $# יוחלף במספר הארגומנטים echo_script > echo_scriptaaabbbccc command: echo_script 3 arguments parameter 1 : aaa parameter 2 : bbb parameter 3 : ccc #!/bin/bash echo command: $0 echo $# arguments let number=1 for paramin $*; do echo parameter $((number++)) : $param done מבוא לתכנות מערכות - 234122
פונקציות • ניתן להגדיר ב-bash פונקציות בצורה כזו: function <name> { <commands> } • פונקציה חייבת להכיל לפחות פקודה אחת • השימוש בפונקציה יכול להתבצע רק אחרי הגדרתה • אפשר להעביר לפונקציה ארגומנטים • הפונקציה משתמשת בהם בדומה לשימושבארגומנטים המועברים לתסריט • הפונקציה אינה יכולה לגשת לארגומנטיםשל התסריט שקרא לה מבוא לתכנות מערכות - 234122
פונקציות • כדי ליצור משתנה מקומי בפונקציה יש להכריז עליו תחילה עם local: > using_local original_aoriginal_b original_asurprise_b using_local #!/bin/bash function surprise { local a=surprise_a b=surprise_b } a=original_a b=original_b echo $a $b surprise echo $a $b מבוא לתכנות מערכות - 234122
פונקציות • ניתן "להחזיר" ערכים מפונקציה בעזרת command subsitution (backticks): > sum_numbers1 2 3 4 5 15 sum_numbers #!/bin/bash function sum { local result=0 for num in $*; do let result+=$num done echo $result } n=`sum $*` echo $n ביטוי זה יוחלף בסכום הרצוי מבוא לתכנות מערכות - 234122
קריאת קלט • ניתן לקרוא שורה מהקלט הסטנדרטי על ידי read <flags> <variable name> • השורה תיקלט לתוך שם המשתנה שהוגדר • הדגל -a יחלק את השורה לפי מילים לתוך מערך • הביטוי read יוחלףעל ידי bash בשורת קלט שתיקלט מהקלט הסטנדרטי > read line Hello world > echo $line Hello world > read -a line Hello world > echo $line Hello > echo ${line[*]} Hello world מבוא לתכנות מערכות - 234122
עבודה עם קבצים • דרך פשוטה לקריאת קובץ היא על ידי שימוש בהפניית קלט ושימוש ב-read: • דרך פשוטה לקרוא קובץ שורה אחר שורה היא כך: > cat hello.txt Hello world! > read line < hello.txt > echo $line Hello world! > cat lines.txt first line second line > lines_counterlines.txt first line second line 2 #!/bin/bash counter=0 while read line; doecho $line let counter++ done < "$1" echo $counter lines_counter מבוא לתכנות מערכות - 234122
חלוקה פונקציונלית של תסריטים • שימו לב שניתן להשתמש ב-bash כדי לערבב תסריטים עם תכניות שנכתבו בשפות שונות בקלות • מכאן מגיע כוחן של שפות תסריטים - scripting languages • ניתן להעביר פרמטרים לתסריטי עזר • בעזרת פרמטרים בשרות הפקודה • בעזרת pipeline • בעזרת קבצים זמניים • ניתן לקבל ערכים חזרה מתסריטי עזר • בעזרת פלט מתסריט העזר מבוא לתכנות מערכות - 234122
העברת והחזרת ערכים • החזרת ערכים מתסריטי העזר יכולה להתבצע בעזרת • שימוש ב-backticks set result = `helper_script` • העברה לתסריט אחר ב-pipeline helper_script | another_script • דרך קובץ זמני helper_script > temp • העברת פרמטרים לתסריטי עזר יכולה להתבצע בדרכים הבאות • בשורת הפקודה helper_script $arg1 $arg2 • בעזרת pipeline echo $arg1 $arg2 | helper_script • דרך קובץ זמני echo $arg1 $arg2 > temp helper_script < temp מבוא לתכנות מערכות - 234122