המצגת נטענת. אנא המתן

המצגת נטענת. אנא המתן

כתיבת תסריטים ב-bash בקרת תהליכים ב-UNIX שאלות ממבחנים

מצגות קשורות


מצגת בנושא: "כתיבת תסריטים ב-bash בקרת תהליכים ב-UNIX שאלות ממבחנים"— תמליל מצגת:

1 כתיבת תסריטים ב-bash בקרת תהליכים ב-UNIX שאלות ממבחנים
תרגול מס' 2 כתיבת תסריטים ב-bash בקרת תהליכים ב-UNIX שאלות ממבחנים

2 הרצת תסריטים מבני בקרה ב-bash דוגמאות השוואה בין C ו-bash
מבוא לתכנות מערכות

3 אוטומציה נניח (מקרה היפותטי לחלוטין) שברשותנו קבצי בדיקה ופלט לתכנית שלנו וברצוננו לבדוק את נכונות התכנית מול קבצים אלו צריך לכתוב 3 פקודות לכל בדיקה גם עם שימוש במנגנון ההיסטוריה הרצת הבדיקות מעיקה ולוקחת הרבה זמן מיותר הפתרון: אוטומטיזציה של הרצת הפקודות. ניצור קובץ אשר יכיל "תסריט" לפיו יורצו כל הפקודות לפי הסדר > mtm_rentals < test1.in > tmpout 2> tmperr > diff expout1 tmpout > diff experr1 tmperr מבוא לתכנות מערכות

4 הרצת תסריט בעזרתsource
ניתן להריץ קובץ המכיל פקודות Bash (להלן תסריט - script) על ידי הפקודה source הפקודות יבוצעו ב-Shell הנוכחי כאילו נכתבו בשורת הפקודה אחת אחרי השניה 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 run_tests > source run_tests Running test 1 Running test 2 Running test 3 אין צורך להדר קבצי תסריט, אלו קבצי טקסט פשוטים. מאחר והפקודות יורצו ב-Shell הנוכחי השפעתיהן יופיעו בו. למשל משתנה שיוגדר בתסריט יישאר מוגדר בסופו. לכן ניתן למשל להגדיר aliases ושינויים ל- PATHבתוך תסריט אשר מורץ באמצעות source מבוא לתכנות מערכות

5 תסריטי אתחול בהתחברות של משתמש למערכת מורץ התסריט .login אשר בתיקית הבית של המשתמש בפתיחת Shell חדש של Bash מורץ התסריט .bashrc הרצות תסריטי האתחול מתבצעות באמצעות source, ולכן הן משפיעות על מצב ה-Shell # 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` .login PATH=$PATH:. alias ll="ls -l" alias cdex2="cd ~mtm/public/1011a/ex2" alias GCC="gcc -std=c99 -Wall \ -pedantic-errors -Werror" .bashrc המשתנה savehist קובע את גודל ההיסטוריה שתישמר בין הרצות של ה-Shell. כך למשל נשמרות פקודות מהפעם הקודמת שהתחברתם ל-stud. מבוא לתכנות מערכות

6 הרצת תסריט כקובץ הרצה ניתן להריץ תסריט כפקודה: #!/bin/bash
בתחילת התסריט יש להוסיף את השורה #!/bin/bash #! מסמן ל-Unix שהשורה הראשונה בקובץ מגדירה את התכנית לביצוע שאר הפקודות בקובץ /bin/bash הוא שם התכנית לביצוע הפקודות, במקרה שלנו Bash בנוסף יש להוסיף הרשאת ריצה לקובץ כעת ניתן להריץ את התסריט כמו תכנית רגילה בניגוד להרצה באמצעות פקודת source התסריט יבוצע בתהליך Shell חדש אשר יסתיים בסוף ריצת התסריט את מיקום bash במחשב ניתן למצוא בעזרת הפקודה which bash כמו שנלמד בתרגול 6 הסימן #! מאפשר הרצה באמצעות כל תכנית שהיא, כך למשל תוכלו לרשום את שם קובץ ההרצה של תרגיל הבית ובהמשך הפקודות לרשום פקודות עבורו לפי השפה שהוגדרה. #!/usr/s02/user/mtm/ex2 item add blah 20 20 report items מבוא לתכנות מערכות

7 הרצת תסריט כקובץ הרצה נמיר את תסריט הרצת הבדיקות שלנו לקובץ הרצה:
#!/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 run_tests נמיר את תסריט הרצת הבדיקות שלנו לקובץ הרצה: בעיה חדשה: התסריט מתחיל להסתבך, הוספת בדיקות נוספות משכפלת קוד בתסריט ולא נוחה (ייתכנו אלפי בדיקות) פתרון: נשתמש במבני בקרה (תנאים ולולאות) בדומה לשפת C > chmod a+x run_tests > ./run_tests Running test 1 Running test 2 Running test 3 בדרך כלל יהיו עשרות-אלפי בדיקות להרצה. אי אפשר להמשיך לשכפל קוד בתסריט. מבוא לתכנות מערכות

8 משתני סביבה ב-bash קיימת אפשרות ליצור משתני סביבה באמצעות הפקודה export כאשר מגדירים משתנה סביבה, המשתנה יוגדר ב- shell הנוכחי ובכל התסריטים אשר יורצו ממנו. זאת בשונה ממשתנה רגיל ב- bash אשר מוגדר אך ורק ב-shell הנוכחי #!/bin/bash echo printing variable LOCAL_X: echo $X echo printing variable ENV_X: echo $ENV_X print_variables > export ENV_X=“10” > LOCAL_X=“15” >./print_variables printing variable LOCAL_X: printing variable ENV_X: 10 > printenv HOSTNAME=tx.technion.ac.il SHELL=/bin/bash USER=mtm PATH=/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin PWD=/homet2/mtm באמצעות הפקודה printenv ניתן לראות את כל משתני הסביבה המוגדרים ב-shell. כאשר מגדירים משתנה סביבה , קיומו מוגדר אך ורק בתוך תהליך ה-shell שממנו נוצר ובכל תהליכי ה- shell אשר נוצרו מתוך תהליך זה. אם נפתח תהליך shell נפרד (לא מתוך ה- shell הנוכחי) משתני הסביבה אשר הגדרנו ב- shell הראשון לא יהיו קיימים בו . לשם כך בדיוק נועדו תסריטי האתחול (bashrc) שימו לב שאם נגדיר משתנה סביבה מתוך סקריפט, המשתנה סביבה יפסיק להתקיים בסיום ריצת הסקריפט ולא נוכל לגשת אליו מתוך ה- shell אשר ממנו הורץ ה-script. מבוא לתכנות מערכות

9 מבני בקרה 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 מבוא לתכנות מערכות

10 while ניתן ליצור לולאות while ב-bash: run_tests
while <expression>; do <command1> <command2> ... done הפקודות בגוף הלולאה יבוצעו כל עוד <expression> ממשיך להתקיים לולאות while כמו שאר מבני הבקרה ניתנות לביצוע ישירות מהטרמינל #!/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 run_tests > i=1 > while (( i <= 3)); do > echo $i > let i++ > done 1 2 3 > ./run_tests Running test 1 Running test 2 Running test 3 התו \ גורם ל-Shell להתעלם מירידית השורה שבאה אחריו ומאפשרת שבירת שורות גדולות (כמו במאקרו ב-C ושורות ב-makefile) התו ; מסמן סוף פקודה ומאפשר כתיבת פקודה חדשה באותה השורה. ניתן היה גם לכתוב: while <expression> do <command1> <command2> ... done מבוא לתכנות מערכות

11 for לולאת for משמשת בדומה לשפת C למעבר נוח יותר על תחום מספרים
#!/bin/bash for ((i = 1; i <= 3; i++)); do echo Running test$i mtm_rentals < test${i}.in > tmpout 2> tmperr diff expout$i tmpout diff experr$i tmperr done run_tests > ./run_tests Running test1.in Running test2.in Running test3.in מבוא לתכנות מערכות

12 for שימוש נוסף ב-for הוא מעבר על על איברי מערך:
for <varname> in <array> ; do <command1> <command2> ... done <varname> הוא שם המשתנה שיכיל בכל פעם איבר מהרשימה <array> הוא רשימה של מחרוזות העדיפו להשתמש בשיטה זו על פני שימוש מפורש באינדקסים הרשימה יכולה להיות {1..10} המספרים 1 עד 10 או למשל {e..y} ואז יודפסו התווים מ e עד y מבוא לתכנות מערכות

13 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 מבוא לתכנות מערכות

14 ביטויים אפשריים ב-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 > if [[ 11 -le 7 ]]; then echo true; fi > if [[ 11 -eq 11 ]]; then echo true; fi > if [[ 0 -eq Hello ]]; then echo true; fi זו אינה השוואת ערכים מספריים עבור ערך שאינו מייצג מספר משתמשים ב-0 לחישוב -eq מתרגם את המחרוזת למספרים, דבר אשר גורם לאיבוד של רווחים בתחילה/סוף משתנה ומשנה את בסיס המספר אם יש ערך המציין זאת בתחילת המחרוזת (למשל, אפסים מובילים אומרים שהמספר הוא בבסיס 8) מבוא לתכנות מערכות

15 התאמת מחרוזות בתוך תנאי מהצורה [[ ]], האופרטור == מאפשר התאמת מחרוזת לתבנית הארגומנט השמאלי הוא מחרוזת רגילה הארגומנט הימני הוא תבנית אשר יכולה לכלול את הסימנים *, ? ו-[ ] כמו שתואר עבור תבניות של שמות קבצים ניתן להשתמש בגרשיים כפולים "" על מנת לבטל את המשמעות המיוחדת של התווים הללו ניתן להשתמש ב- ^ עבור שלילה של תו מסוים. האופרטור =! הוא השלילה של אופרטור ההתאמה == המשמעות של = ו-== זהה > end_with_z="some string with z" > if [[ "$end_with_z" = *[zZ] ]]; then echo match; fi match > if [[ "this string starts 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 מבוא לתכנות מערכות

16 ביטויים אפשריים ב-if ו-while
בתוך [[ ]] ניתן להשתמש בתנאים מועילים נוספים, למשל: התנאי -f <filename> בודק האם קיים קובץ בשם <filename> התנאי -d <dirname> בודק האם קיימת תיקייה בשם <dirname> ניתן לבדוק תנאים מורכבים יותר: ניתן להשתמש באופרטורים &&, ||, ו-! כמו בשפת C הקפידו להשאיר רווח אחרי ! כדי להימנע משגיאות בגלל מנגנון ההיסטוריה ניתן להשתמש בסוגריים כדי לקבוע את הקדימויות > if [[ -f a.txt ]]; then echo file exists; fi > cat > a.txt Hello world! file exists > mkdir mtm > if [[ ! (-f b.txt && -d mtm) ]]; then echo yes; fi yes מבוא לתכנות מערכות

17 ביטויים אפשריים ב-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 > if (( 0 == Hello )); then echo true; fi > if (( ++i == 6 )); then echo true; fi מבוא לתכנות מערכות

18 העברת פרמטרים בשורת הפקודה
כמו ב-C ניתן לגשת לפרמטרים המועברים בשורת הפקודה לתסריט הפרמטר ה-n לתסריט נקרא פשוט n, וניתן לקרוא אותו על ידי $n $* יוחלף ברשימת כל הארגומנטים לתסריט אם ייתכנו רווחים בתוך הארגומנטים ניתן להשתמש כדי לשמור על מספר האגומנטים הנכון $0 יוחלף בשם התסריט $# יוחלף במספר הארגומנטים #!/bin/bash echo command: $0 echo $# arguments let number=1 for param in $*; do echo parameter $((number++)) : $param done echo_script > echo_script aaa bbb ccc command: echo_script 3 arguments parameter 1 : aaa parameter 2 : bbb parameter 3 : ccc מבוא לתכנות מערכות

19 פונקציות ניתן להגדיר ב-bash פונקציות בצורה כזו:
function <name> { <commands> } פונקציה חייבת להכיל לפחות פקודה אחת השימוש בפונקציה יכול להתבצע רק אחרי הגדרתה אפשר להעביר לפונקציה ארגומנטים הפונקציה משתמשת בהם בדומה לשימוש בארגומנטים המועברים לתסריט הפונקציה אינה יכולה לגשת לארגומנטים של התסריט שקרא לה מבוא לתכנות מערכות

20 פונקציות כדי ליצור משתנה מקומי בפונקציה יש להכריז עליו תחילה עם local:
#!/bin/bash function surprise { local a=surprise_a b=surprise_b } a=original_a b=original_b echo $a $b surprise using_local > using_local original_a original_b original_a surprise_b מבוא לתכנות מערכות

21 ביטוי זה יוחלף בסכום הרצוי
פונקציות ניתן "להחזיר" ערכים מפונקציה בעזרת command subsitution (backticks): #!/bin/bash function sum { local result=0 for num in $*; do let result+=$num done echo $result } n=`sum $*` echo $n sum_numbers > sum_numbers 15 ביטוי זה יוחלף בסכום הרצוי מבוא לתכנות מערכות

22 קריאת קלט ניתן לקרוא שורה מהקלט הסטנדרטי על ידי read <flags> <variable name> השורה תיקלט לתוך שם המשתנה שהוגדר הדגל -a יחלק את השורה לפי מילים לתוך מערך הביטוי read יוחלף על ידי bash בשורת קלט שתיקלט מהקלט הסטנדרטי > read line Hello world > echo $line > read -a line Hello > echo ${line[*]} מבוא לתכנות מערכות

23 עבודה עם קבצים דרך פשוטה לקריאת קובץ היא על ידי שימוש בהפניית קלט ושימוש ב-read: דרך פשוטה לקרוא קובץ שורה אחר שורה היא כך: > cat hello.txt Hello world! > read line < hello.txt > echo $line #!/bin/bash counter=0 while read line; do echo $line let counter++ done < "$1" echo $counter lines_counter > cat lines.txt first line second line > lines_counter lines.txt first line 2 מבוא לתכנות מערכות

24 חלוקה פונקציונלית של תסריטים
שימו לב שניתן להשתמש ב-bash כדי לערבב תסריטים עם תכניות שנכתבו בשפות שונות בקלות מכאן מגיע כוחן של שפות תסריטים - scripting languages ניתן להעביר פרמטרים לתסריטי עזר בעזרת פרמטרים בשרות הפקודה בעזרת pipeline בעזרת קבצים זמניים ניתן לקבל ערכים חזרה מתסריטי עזר בעזרת פלט מתסריט העזר מבוא לתכנות מערכות

25 העברת והחזרת ערכים החזרת ערכים מתסריטי העזר יכולה להתבצע בעזרת
שימוש ב-backticks 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 פרמטרים המועברים בשורת הפקודה ייקראו מהתסריט שקיבל אותם על ידי גישה לפרמטרים של שורת הפקודה. מידע המועבד דרך pipeline ייקרא בתסריט העזר על ידי קראיה מהקלט הסטנדרטי שלו בכל מקרה, החזרת הערכים מתבצעת על ידי הדפסה בתסריט העזר. מומלץ לא להעביר פרמטרים דרך קבצים זמניים, שיטה זו פחות עמידה לבאגים ומושפעת ממצב הקבצים בספריה )קל גם בטעות לשכוח קבצים זמניים בלי למחוק אותם בסוף הריצה) מבוא לתכנות מערכות

26 exit ניתן להשתמש בפקודה exit על מנת לצאת מה-shell הנוכחי ולהחזיר ערך יציאה נבחר: exit [status] ערך בררת המחדל הוא 0 – ומייצג "הצלחה" של התוכנית. כל ערך אחר (מספר שלם) אמור לייצג כישלון. בכל רגע נתון ערך היציאה האחרון שמור במשתנה $? #!/bin/bash echo "hi" exit 1 echo "bye" example_script > ./example_script hi > echo $? 1 כל תוכנית אמורה לסיים את ריצתה עם ערך יציאה (עבור תוכנית שנכתבה ב-C זהו אותו ערך שפונקציית ה-main מחזירה). מבוא לתכנות מערכות

27 דוגמה כתבו תסריט בשם search אשר מקבל מחרוזת ושמות קבצים ומדפיס את כל השורות המופיעות בקבצים הללו המכילות את המחרוזת המבוקשת אם מתקבל שם תיקיה, ייבדקו כל הקבצים תחת התיקיה הזו רקורסיבית > search Blue scene35.txt scene35.txt : 37 : LAUNCELOT: Blue. scene35.txt : 55 : GALAHAD: Blue. No yel-- Auuuuuuuugh! > search swallow scene*.txt scene1.txt : 50 : GUARD #1: But then of course African swallows are not migratory. scene1.txt : 54 : GUARD #2: Wait a minute -- supposing two swallows carried it together? scene35.txt : 63 : BEDEMIR: How do know so much about swallows? > search cow farms farms/animals/animals.txt : 8 : cow farms/farm1.txt : 2 : cow Betsy farms/farm1.txt : 3 : slim cow Dazy farms/farm1.txt : 4 : fat cow Burger farms/farm1.txt : 5 : two cows Dartsy & Teo farms/farm2.txt : 2 : cow Leni farms/farm2.txt : 4 : cow Oreo מבוא לתכנות מערכות

28 פתרון נכתוב תסריט בשם search search
התסריט ישתמש בפונקצית עזר הקוראת קובץ ומוצאת את השורות המתאימות בעזרת התאמת מחרוזות #!/bin/bash function search_file { n=1 while read line; do if [[ $line = *"$1"* ]]; then echo “${2} : ${n} : $line” fi let n++; done < "$2" } for file in ${*:2}; do if [[ -f "$file" ]]; then search_file "$1" $file if [[ -d "$file" ]]; then search "$1" $file/* done search שימו לב לשימוש במרכאות: $1 מופיע במרכאות תמיד כי זו מחרוזת חיפוש והיא עלולה להכיל יותר ממילה אחת! ללא המרכאות המחרוזת "Hello world" תועבר כשני פרמטרים ל-search_in_file ונקבל באג. מבוא לתכנות מערכות

29 דוגמה נוספת football.txt
Alon Miz. 2 23/10/93 Macabi-Haifa Macabi-Tel-Aviv Izak Zoh. 1 12/11/93 Macabi-Tel-Aviv Hapoel-Beer-Sheva Ronen Ha. 3 27/12/93 Hapoel-Tel-Aviv Macabi-Tel-Aviv Reuven A. 2 12/11/93 Macabi-Haifa Hapoel-Tel-Aviv Eyal Ber /11/93 Macabi-Haifa Macabi-Tel-Aviv Izak Zoh. 1 12/11/93 Macabi-Tel-Aviv Hapoel-Haifa Alon Miz. 2 26/10/93 Macabi-Haifa Beitar-Jerusalem Izak Zoh. 2 12/12/93 Macabi-Tel-Aviv Macabi-Hiafa Alon Miz. 2 23/12/93 Macabi-Haifa Macabi-Pet-Tikva Ronen Ha. 3 27/11/93 Hapoel-Tel-Aviv Macabi-Haifa football.txt נתון קובץ בשם football.txt המכיל נתונים על שערים שהובקעו במשחקי כדורגל כל שורה בקובץ מציינת שם של שחקן, מספר השערים שהבקיע במשחק שנערך בתאריך מסוים, שם הקבוצה בה הוא שיחק ושם הקבוצה היריבה ברצוננו לכתוב תסריט בשם player אשר יקבל כפרמטר שם של שחקן וידפיס את כל השורות עבורו מהקובץ football.txt ואת סכום מספר השערים שהבקיע > player "Alon Miz." Alon Miz. 2 23/10/93 Macabi-Haifa Macabi-Tel-Aviv Alon Miz. 2 26/10/93 Macabi-Haifa Beitar-Jerusalem Alon Miz. 2 23/12/93 Macabi-Haifa Macabi-Pet-Tikva Total number of goals: 6 מבוא לתכנות מערכות

30 פתרון נשתמש בתסריט search שכתבנו מקודם כדי לקבל רק את השורות הרלוונטיות נכתוב פונקצית עזר בשם calc_total אשר תקרא את השורות מהקלט הסטנדרטי שלה ותסכום את מספר הגולים של השחקן תוך כדי הדפסתן #!/bin/bash function calc_total { sum=0 while read -a line; do let sum+=${line[6]} echo ${line[*]:4} done echo "total number of goals: $sum" } search "$1" football.txt | calc_total player מבוא לתכנות מערכות

31 דוגמה שלישית כתבו תסריט לדירוג שחקנים בשם best_player אשר יקבל רשימה של שמות שחקנים בשורת הפקודה וידפיס את שם השחקן שהבקיע את מרב הגולים אם קיימים מספר שחקנים שהבקיעו את מרב הגולים יודפסו שמות כל השחקנים לכל שחקן יש להדפיס את שמו ומספר הגולים שהבקיע > best_player "Alon Miz." "Izak Zoh." "Ronen Ha." "Reuven A." Alon Miz. 6 Ronen Ha. 6 מבוא לתכנות מערכות

32 פתרון best_player #!/bin/bash # Sums the goals from lines in
# the correct format function sum_goals { local sum=0 while read -a line; do let sum+=${line[6]} done echo $sum } # Sums all the goals of target player function sum_player_goals { ./search "$1" football.txt | sum_goals best_player max_goals=0 for player in do goals=`sum_player_goals "$player"` if (( goals > max_goals )); then max_goals=$goals fi done if (( goals >= max_goals )); then echo "$player" $max_goals תכנון נכון יותר של בחירת תסריטי העזר יכולה לאפשר לנו להשתמש בתסריטים מהסעיף הקודם כאן, בתרגול 1 ראינו כלים סטנדרטיים של Unix שמאפשרים לנו פתרון נוח יותר של בעיות כאלו. מבוא לתכנות מערכות

33 השוואה בין bash ל-C Bash היא שפת תסריטים - scripting language
שפות תסריטים נוספות: Perl, Tcl, Python, Ruby. C היא שפת תכנות מערכת - system programming language שפות מערכת נוספות: C++, Java, C#. מבוא לתכנות מערכות

34 השוואה בין bash ל-C יתרונות של bash על C: חסרונות של bash לעומת C:
עבודה נוחה עם מחרוזות ומשתנים נוח "להדביק" תכניות קיימות (עוד על כך בתרגול 7) קוד קצר משמעותית לחלק מהמשימות אין קומפיילר - לא צריך להכריז על דברים חסרונות של bash לעומת C: אין קומפיילר - אין בדיקות מאפשר באגים מסוכנים איטית (לעתים פי כמה מאות) נבחר ב- bash עבור מטלות פשוטות וקצרות שזמן הביצוע שלהן לא קריטי read deposits account_balance=100 for d in ${deposits[*]}; do acount_balance=$((account_balance + d)) done echo $account_balance הבאג בקוד הוא בגלל איות לא נכון של המילה account בהשמה, רשום acount_balance עם c אחת בלבד. כתוצאה מכך ההפקדות לא מתבצעות לחשבון. שגיאה מסוכנת כזו בכלל לא תתקמפל ב-C. Benchmark comparisons of tcl and perl to C מבוא לתכנות מערכות

35 bash- סיכום כדי לחסוך ביצוע חוזר וידני של פעולות ניתן ליצור תסריטים המכילים רצף פקודות שימושי ולהריצם בעזרת source או הפיכתם לקובץ הרצה ב-bash קיימים מבני הבקרה while , for ו if המאפשרים כתיבת קוד מתקדם בתסריטים ניתן לגשת לפרמטרים לשרות הפקודה של תסריט בדומה לתכנית ב-C כדי לקרוא מהקלט הסטנדרטי ב-bash נשתמש בפקודה read ניתן לחלק תסריטים לפונקציות ולהעביר מידע ביניהן ע"י קריאת טקסט בפונקציה וכתיבתו לפלט נוח להדביק תסריטים ביחד בעזרת pipeline ו-command substitution כדי לפתור בקלות בעיות נשתמש ב-bash עבור מטלות פשוטות שאינן דורשות חישובים רבים, עבור שאר המטלות נמשיך להשתמש ב-C מבוא לתכנות מערכות

36 שימוש בתכניות סטנדרטיות של Unix בתסריטים
שאלות ממבחנים - bash שימוש בתכניות סטנדרטיות של Unix בתסריטים מבוא לתכנות מערכות

37 שאלה 1 ( ) כתוב תכנית ב-bash ששמהarrange אשר מעבירה קבצים מהתיקיה הנוכחית (שאינם תיקיות) לתוך תתי-תיקיות לפי הכללים הבאים: לכל קובץ שאינו תיקיה: אם קיימת תת-תיקיה לתיקיה הנוכחית ששמו זהה ל-4 האותיות הראשונות בשם הקובץ, הקובץ יועבר לתוך התיקיה. (שים לב שהכוונה להעברת הקובץ ולא להעתקתו). אם תנאי 1 לא מתקיים, וקיימים לפחות שני קבצים נוספים בתיקיה הנוכחית שאינם תיקיות, כך ש-4 האותיות הראשונות בשמם זהות ל-4 האותיות הראשונות בשם הקובץ, התוכנית תיצור תת-תיקיה חדשה ששמה זהה ל-4 האותיות הראשונות בשם הקובץ, והקובץ יועבר לתוך תת-תיקיה זו. מבוא לתכנות מערכות

38 שאלה 1 ( ) - דוגמה במדריך הנוכחי קיימים הקבצים הבאים: file1 file2 file3 prog1 prog2 prog script1 script2 כאשר רק הקובץ prog הינו תיקיה לאחר הפעלת התוכנית arrange בתיקיה הנוכחית, יהיו הקבצים הבאים בתיקיה זו: file script1 script2 prog כאשר: file ו – prog הינם תיקיות בתיקיה file יהיו הקבצים file1 file2 file3 בתיקיה prog יהיו הקבצים prog1 ו - prog2 (בנוסף לקבצים שהיו בתוכו לפני הפעלת התוכנית arrange). file1 file2 file3 script1 script2 prog prog1 prog2 file1 file2 file3 prog1 prog2 file script script prog מבוא לתכנות מערכות

39 פתרון arrange #!/bin/bash function files { for f in `ls`; do
if [[ -f $f ]]; then echo $f fi done } function fileCount { line=( `files | cut -c1-4 | sort | uniq -c | grep $1` ) echo ${line[0]} function makeDir { if [[ ! -d $1 ]] ; then mkdir $1 arrange מבוא לתכנות מערכות

40 פתרון arrange for file in `ls` ;do if [[ ! -f $file ]] ; then continue
dirOfFile="`echo $file | cut -c1-4`" numOfFiles=`fileCount "$dirOfFile"` if (( numOfFiles > 2 )) ; then makeDir $dirOfFile if [[ -d $dirOfFile ]] ; then mv $file $ dirOfFile done arrange לכל קובץ, נבדוק האם קיימים מספיק קבצים עם אותם 4 אותיות בתחילת השם. אם כן, ניצור תיקייה מתאימה. לאחר מכן, אם יש תיקייה מתאימה (בין אם נוצרה או הייתה קיימת) נזיז את הקובץ לתיקייה. מבוא לתכנות מערכות

41 שאלה 2 (מועד ג', אביב 2006) חברת Moogle, שהחליטה זה מכבר לפתוח סניף בחיפה, הכריזה על יום ראיונות בפקולטה למדעי המחשב בטכניון (אשר בהם יכולים להשתתף רק בוגרי קורס מת"ם כמובן). במהלך הראיונות נוכחים מספר מראיינים ובינהם גם מנהל Moogle. כל מראיין נותן ציון למרואיין בין 0 ל-100. הציון הסופי יקבע ע"י שקלול כל הציונים. למנהל יש זכות וטו ולא יתכן כי יתקבל לעבודה מרואיין שהמנהל החליט לא לקבל. בסיום הראיונות כל מראיין מכין קובץ בפורמט הבא על האנשים אותם הוא ראיין: <ID> <FULL NAME> <GRADE> השדות מופרדים זה מזה בטאבים. שם הקובץ הינו <interviewer name>.grades. דוגמה לקובץ בשם eyal.grades: הקובץ של מנהל Moogle ייקרא Moogle.grades ויכול להיראות כך: Moshe Levi 60 Shimon Cohen 90 David David 100 Moshe Levi 57 David David -NO- Shimon Cohen 80 מבוא לתכנות מערכות

42 שאלה 2 (מועד ג', אביב 2006) עליכם לכתוב תסריט בשם BestToWork אשר ינתח את הקבצים הללו ויחזיר את קבוצת המרואיינים הטובים ביותר. התסריט יקבל כפרמטר את מס' מקומות העבודה הפנויים ויחזיר מס' שכזה של מרואיינים מצטיינים ממויינים לפי מידת ההצלחה. במקרה שאין מספיק מרואיינים שהתראיינו / עברו את הראיון, תוחזר ההודעה: "not enough interviewees” לדוגמה, עבור שני הקבצים שבדוגמה: הערות: הניחו כי קבצי הקלט קיימים ותקינים ניתן להניח שאותם מראיינים ראיינו את כל האנשים אין להשתמש בקבצים זמניים ניתן להשתמש במספר לא מוגבל של תסריטים > BestToWork 2 1) Shimon Cohen 2) Moshe Levi > BestToWork 3 not enough interviewees מבוא לתכנות מערכות

43 פתרון BestToWork #!/bin/bash function PrintBest { local num=1
while read -a line; do echo "${num}) ${line[0]} ${line[1]} ${line[2]}" let num++ done } function CalcOneGrade { local total_grade=0 let total_grade+=${line[3]} echo $total_grade BestToWork מבוא לתכנות מערכות

44 פתרון BestToWork function CalcGrades { while read -a line; do
grade=`cat *.grades | grep ${line[0]} | CalcOneGrade` echo ${line[0]} ${line[1]} ${line[2]} $grade done } if (( `cat Moogle.grades | grep -v "\-NO\-" | wc -l` < $1 )) ; then echo "not enough interviewees" else cat Moogle.grades | grep -v "\-NO\-" | CalcGrades | \ sort –nrk4 | PrintBest | head -$1 fi BestToWork מבוא לתכנות מערכות


הורד את "ppt "כתיבת תסריטים ב-bash בקרת תהליכים ב-UNIX שאלות ממבחנים

מצגות קשורות


מודעות Google