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

Slides:



Advertisements
מצגות קשורות
הכרת תוכנת בקרים. כניסה לתוכנה תתבצע בשלבים הבאים: 1
Advertisements

תכנות בשפת C תרגול 11 - קבצים.
הרצאה 02 סוגי משתנים קרן כליף.
קורס ניהול ידע מפגש 3 - פורטלים 2know.kmrom.com.
יצירת מקרו הפעלת מקרו יצירת לחצן / פקד דוגמה מסכמת
מבוא לתכנות ב-JAVA מעבדה 1
טיפים מנצחים: לחפש ולמצוא במהירות ובדיוק
תרגול 11: רקורסיה ופיתוח טלסקופי
תרגול 1: סביבת העבודה ומבוא ל-Java
לולאות Department of Computer Science-BGU 19 יולי 19.
נערך ע"י אריק הוד, הגימנסיה העברית הרצליה
תרגול 5: לולאות ומערכים.
מבוא למדעי המחשב מ' - תירגול 9
תירגול 10: מבנים (structs) וקבצים
Marina Kogan Sadetsky –
עבודה ב-T2 מבוא לתכנות מערכות.
Jump tables, review questions
הרצאה 3: משפטים, תנאים ולולאות
מבוא למדעי המחשב הרצאה מספר 12: רקורסיה
תכנות בשפת C תרגול 11 רשימות מקושרות מבנים
תרגול Introduction to C - Fall Amir Menczel.
פעולות אריתמטיות קרן כליף.
Computer Programming תרגול 1 Summer 2016
תירגול 11: מיונים וחיפוש בינארי
נערך ע"י אריק הוד הגימנסיה העברית הרצליה

Entity Relationship Diagram – ERD
תירגול 3: לולאות, קלט, וטיפוסים
תכנות בשפת C תרגול 8 רקורסיה
חשבון זה הוא חלק ממוצרי 365 ומקושר לתיבת המייל
Engineering Programming A
תרגול 6: פונקציות, סוגי משתנים, top-down design
תהליך ההרשמה לבעלי אימייל של המכללה, ניתן להכנס לכתובת הבאה וליצור חשבון:
תירגול 2: מבוא לתיכנות ב-C
כל הזכויות שמורות לגבריאל אנקרי © 2017
© המרכז להוראת המדעים האוניברסיטה העברית בירושלים
מבוסס על שקפים מאת יאן ציטרין
הרצאה 10: אלגוריתמי מיון רקורסיביים Merge sort ו-Quick sort
תורת הקומפילציה תרגול 9: תרגום לקוד ביניים
מבוא לתכנות למערכות מידע
Computer Architecture and System Programming Laboratory
אלגוריתמי מיון רקורסיביים
כל הזכויות שמורות לגבריאל אנקרי © 2017
תרגול 13 : חזרה נכתב על-ידי לימור ליבוביץ נערך ע"י ישראל גוטר
Marina Kogan Sadetsky –
CLI vs GUI.
מת"מ מעבדה 7-8 רשימות.
© המרכז להוראת המדעים האוניברסיטה העברית בירושלים
שימוש בעצם ממחלקה אחרת כמאפיין במחלקה הנוכחית
מבוא לתכנות ב- JAVA מעבדה 4
SQL: מושגים עמודה, תכונה, שדה, אטריביוט טבלה, רלציה סכמה
מבוא לתכנות בWINDOWS ד"ר אבי רוזנפלד.
מבנה כללי של היררכיית הקבצים עבור המסלול /A/B.txt
מבוא למדעי המחשב סמסטר ב' – 2008 מרצה: יעל סיגל מתרגל: ענבל בודובסקי.
מצביעים Pointers – המשך...
הצג את עצמך, את עמותת תפוח ואת נושא הפעילות.
מעבדה 2- עיצוב (עבור חלק ג)
ברוכים הבאים למת"ם מבוא לתכנות מערכות הוכן ע"י שרי דואק
מערכת הערעורים מסכי סטודנטים.
עקרונות תכנות מונחה עצמים תרגול 9:C++ - תרגילים
תכניות סטנדרטיות ב- UNIX שאלות ממבחנים
והתאמתה למאפייני הסטודנטים
Java Programming רשימות מקושרות - המשך
הפונקציה מחזירה את מספר התווים במחרוזת נתונה.
Engineering Programming A
רשימות מקושרות עבודה עם קבצים דוגמה
תמליל מצגת:

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

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

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

הרצת תסריט בעזרת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 מבוא לתכנות מערכות - 234122

תסריטי אתחול בהתחברות של משתמש למערכת מורץ התסריט .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. מבוא לתכנות מערכות - 234122

הרצת תסריט כקובץ הרצה ניתן להריץ תסריט כפקודה: #!/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 מבוא לתכנות מערכות - 234122

הרצת תסריט כקובץ הרצה נמיר את תסריט הרצת הבדיקות שלנו לקובץ הרצה: #!/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 בדרך כלל יהיו עשרות-אלפי בדיקות להרצה. אי אפשר להמשיך לשכפל קוד בתסריט. מבוא לתכנות מערכות - 234122

משתני סביבה ב-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. מבוא לתכנות מערכות - 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: 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 מבוא לתכנות מערכות - 234122

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

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

התאמת מחרוזות בתוך תנאי מהצורה [[ ]], האופרטור == מאפשר התאמת מחרוזת לתבנית הארגומנט השמאלי הוא מחרוזת רגילה הארגומנט הימני הוא תבנית אשר יכולה לכלול את הסימנים *, ? ו-[ ] כמו שתואר עבור תבניות של שמות קבצים ניתן להשתמש בגרשיים כפולים "" על מנת לבטל את המשמעות המיוחדת של התווים הללו ניתן להשתמש ב- ^ עבור שלילה של תו מסוים. האופרטור =! הוא השלילה של אופרטור ההתאמה == המשמעות של = ו-== זהה > 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 מבוא לתכנות מערכות - 234122

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

העברת פרמטרים בשורת הפקודה כמו ב-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 מבוא לתכנות מערכות - 234122

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

פונקציות כדי ליצור משתנה מקומי בפונקציה יש להכריז עליו תחילה עם 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 מבוא לתכנות מערכות - 234122

ביטוי זה יוחלף בסכום הרצוי פונקציות ניתן "להחזיר" ערכים מפונקציה בעזרת 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 1 2 3 4 5 15 ביטוי זה יוחלף בסכום הרצוי מבוא לתכנות מערכות - 234122

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

עבודה עם קבצים דרך פשוטה לקריאת קובץ היא על ידי שימוש בהפניית קלט ושימוש ב-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 מבוא לתכנות מערכות - 234122

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

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

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

דוגמה כתבו תסריט בשם 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 מבוא לתכנות מערכות - 234122

פתרון נכתוב תסריט בשם 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 ונקבל באג. מבוא לתכנות מערכות - 234122

דוגמה נוספת 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. 1 20/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 מבוא לתכנות מערכות - 234122

פתרון נשתמש בתסריט 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 מבוא לתכנות מערכות - 234122

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

פתרון 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 שמאפשרים לנו פתרון נוח יותר של בעיות כאלו. מבוא לתכנות מערכות - 234122

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

השוואה בין 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 http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=tcl&lang2=gcc http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=perl&lang2=gcc מבוא לתכנות מערכות - 234122

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

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

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

שאלה 1 (21.7.95) - דוגמה במדריך הנוכחי קיימים הקבצים הבאים: 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 script1 script2 prog מבוא לתכנות מערכות - 234122

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

פתרון 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 אותיות בתחילת השם. אם כן, ניצור תיקייה מתאימה. לאחר מכן, אם יש תיקייה מתאימה (בין אם נוצרה או הייתה קיימת) נזיז את הקובץ לתיקייה. מבוא לתכנות מערכות - 234122

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

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

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

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