תרגול 7 תסריטים ניהול תהליכים ב -UNIX לי-טל משיח נערך והורחב ע'' ודים אייזנברג
תסריטים - דוגמא למוטיבציה נניח, אנו מפתחים תוכנה בשם mtm_bank ואנחנו רוצים להריץ עליה טסטים בצורה הבאה : יש לנו מספר טסטים, לכל טסט, שמספרו N ישנם : –קובץ קלט testN.in –קובץ הפלט הרגיל המצופה expoutN –קובץ פלט השגיאות המצופה experrN הפקודה diff משוואה בין הקבצים שהתקבלו לקבצים המצופים 2 > ( mtm_bank ! tmpout ) > & ! tmperr > diff expout1 tmpout > diff experr1 tmperr > ( mtm_bank ! tmpout ) > & ! tmperr > diff expout1 tmpout > diff experr1 tmperr
הבעיה - יעילות העבודה לכל טסט יש להריץ 3 פקודות מתכנת רציני יכתוב הרבה טסטים לתוכנית שלו –בתוכנה האמיתית - אלפי טסטים עבודה שחורה וסיזיפיתניתן להקליד את הפקודות אחת אחרי השנייה - עבודה שחורה וסיזיפית 3
הבעיה - יעילות העבודה 4 Attribution : / CC BY BY 3.0http:// BY 3.0
הפתרון - תסריטים רושמים את כל הפקודות בקובץ תסריט (script) מריצים את התסריט על ידי הקשת פקודה אחת כל הפקודות בקובץ התסריט מתבצעות אחת אחרי השנייה, כאילו שהקלדנו אותן בשורת הפקודה 5 ( mtm_bank ! tmpout ) > & ! tmperr diff expout1 tmpout diff experr1 tmperr ( mtm_bank ! tmpout ) > & ! tmperr diff expout2 tmpout diff experr2 tmperr ( mtm_bank ! tmpout ) > & ! tmperr diff expout3 tmpout diff experr3 tmperr ( mtm_bank ! tmpout ) > & ! tmperr diff expout1 tmpout diff experr1 tmperr ( mtm_bank ! tmpout ) > & ! tmperr diff expout2 tmpout diff experr2 tmperr ( mtm_bank ! tmpout ) > & ! tmperr diff expout3 tmpout diff experr3 tmperr Text File: run_tests
תסריטים ( קבצי script) קבצים סדרה של פקודותקבצים אשר מכילים סדרה של פקודות shell תוכניות שפת ה -shell –מהווים מעין תוכניות הכתובות בשפת ה -shell קובץ טקסטנכתבים בקובץ טקסט רגיל –ניתן להריץ אותם מספר פעמים –אין צורך בהידור sourceמריצים על ידי הפקודה source > source run_tests –אפשרות אחרת של הרצה - בהמשך התרגול 6
שפת התסריטים C-shell שפת תכנותשפת התסריטים C-shell היא שפת תכנות לכל דבר –משתנים כולם מאותו טיפוס - מחרוזת או רשימה של מחרוזות –פעולות אריתמטיות רק בשלמים –לולאות –לולאות (while ואחרות ) –משפטי תנאי –משפטי תנאי (if else) –הערות –הערות : מסימן # ועד סוף השורה בדומה לשפת C –,goto, switch ודברים אחרים בדומה לשפת C 7 בשביל מה צריך עוד שפת תכנות ??? התשובה בסוף התרגול
ניצול יכולות של C-shell בכתיבת תסריטים ניתן להיעזר בכל היכולות של C-shell שלמדנו : –משתנים – Alias Substitution – File name expansion – Command Substitution backticks `` – I/O redirection – pipelining 8
תסריט run_tests- הבעיה לא יעיל לרשום את כל הפקודות עבור כל הטסטים –מספר הטסטים בתוכנה האמיתית יכול להגיע לאלפים רבים 9 ( mtm_bank ! tmpout ) > & ! tmperr diff expout1 tmpout diff experr1 tmperr ( mtm_bank ! tmpout ) > & ! tmperr diff expout2 tmpout diff experr2 tmperr ( mtm_bank ! tmpout ) > & ! tmperr diff expout3 tmpout diff experr3 tmperr ( mtm_bank ! tmpout ) > & ! tmperr diff expout1 tmpout diff experr1 tmperr ( mtm_bank ! tmpout ) > & ! tmperr diff expout2 tmpout diff experr2 tmperr ( mtm_bank ! tmpout ) > & ! tmperr diff expout3 tmpout diff experr3 tmperr
לולאות ב - C-shell: while 10 while ( ) end > source count > source count # count10 i = 0 while ($i<10) echo i++ end # count10 i = 0 while ($i<10) echo i++ end
run_tests2 - שימוש ב -while 11 # run_tests2 set TESTS_NUMBER = 3 set i = 1 while ( $i <= $TESTS_NUMBER) echo running test $i ( mtm_bank ! out$i ) > & ! err$i diff expout$i out$i diff experr$i i++ end # run_tests2 set TESTS_NUMBER = 3 set i = 1 while ( $i <= $TESTS_NUMBER) echo running test $i ( mtm_bank ! out$i ) > & ! err$i diff expout$i out$i diff experr$i i++ end
לולאות ב - C-shell: repeat cshell מבצע את הפקודה command בדיוק count פעמים : להריץ גם ב - command lineשימו לב שכל לולאה של C-shell ניתן להריץ גם ב - command line 12 repeat repeat <repeat 3 echo Congratulations, Shifra ! Congratulations, Shifra ! > <repeat 3 echo Congratulations, Shifra ! Congratulations, Shifra ! >
לולאות ב - C-shell: foreach הלולאה מתבצעת מספר פעמים השווה לגודל הרשימה list בכל איטרציה מקבל ערך אחד מהרשימהבכל איטרציה של הלולאה, המשתנה variable מקבל ערך אחד מהרשימה לפי הסדר 13 foreach ( ) end
foreach : דוגמאות 14 # final_vote script set number = 1 foreach name (Itai Yossi Leon Einav Shifra) echo for $name send the number number++ end # final_vote script set number = 1 foreach name (Itai Yossi Leon Einav Shifra) echo for $name send the number number++ end > source final_vote for Itai send the number 1 for Yossi send the number 2 for Leon send the number 3 for Einav send the number 4 for Shifra send the number 5 > source final_vote for Itai send the number 1 for Yossi send the number 2 for Leon send the number 3 for Einav send the number 4 for Shifra send the number 5
תסריט 2 run_tests- הבעיה מספר הטסטים המורצים נקבע על ידי המשתנה TESTS_NUMBER צריך לעדכן אותו כל פעם שמוסיפים טסט חדש 15 # run_tests2 set TESTS_NUMBER = 3 set i = 1 while ( $i <= i++ end # run_tests2 set TESTS_NUMBER = 3 set i = 1 while ( $i <= i++ end
run_tests3 - שימוש ב -foreach כל פעם שנוסיף טסט חדש - קובץ קלט וקבצי הפלט המצופים, התסריט יריץ אותם בלי שום התערבות שלנו –אין צורך לשנות את התסריט כל פעם שמוסיפים / מורידים טסטים 16 # run_tests3 foreach FILE (*.in) set i = `echo $FILE | cut -c5- | cut -f1 -d.` echo running test $i ( mtm_bank ! out$i ) > & ! err$i diff expout$i out$i diff experr$i err$i end # run_tests3 foreach FILE (*.in) set i = `echo $FILE | cut -c5- | cut -f1 -d.` echo running test $i ( mtm_bank ! out$i ) > & ! err$i diff expout$i out$i diff experr$i err$i end
משפטי תנאי (if... else) שתי גרסאותשתי גרסאות : פקודה אחת – if עם פקודה אחת, בלי else if ( ) if ( ) כמה פקודות אופציה ל -else – if עם כמה פקודות ועם אופציה ל -else if ( ) then [else ] ]endif 17 בגרסה הזאת חייבים then בגרסה הזאת חייבים then וגם endif
דוגמא של if if ($votes_for_yossi > $votes_for_shifra) then echo Yossi won ! else echo Shifra won ! endif 18
תנאים בתוך משפטי if השוואת מחרוזות : if ($winner == "Yossi") … השוואת מספרים : if ($votes > ) … תנאים מיוחדים ל -C-shell if (-d aaa)... התיקייה –משוערך ל -true אם התיקייה בשם aaa קיימת בתוך התיקייה הנוכחית if (-f aaa)... הקובץ והוא לא תיקייה –משוערך ל -true אם הקובץ בשם aaa קיים בתיקייה הנוכחית ( והוא לא תיקייה ) 19
תנאים בתוך משפטי if- התאמת מחרוזות ~= אופרטור ~= המחרוזת בצד שמאל תבנית בצד ימין –משוערך ל -true אם המחרוזת בצד שמאל מתאימה לתבנית בצד ימין סימנים מיוחדיםהתבנית יכולה לכלול סימנים מיוחדים כגון : *,? או [] שמשמעותם תוארה בתרגול הקודם השלילה ~!השלילה של האופרטור ~= היא ~! 20
תנאים בתוך משפטי if: התאמה בין מחרוזות אופרטורים =~, !~ 21 > if (end_with_z =~ *[zZ]) echo match match > if ("no point in string" !~ *.*) echo "no point" no point > if ("point -. - in string" !~ *.*) echo "no point" >
סיכום : אופרטורים בתוך משפטי if אופרטורים של השוואהאופרטורים של השוואה מספרים –, = משווים בין מספרים מחרוזות – ==, =!, ~=, ~! משווים בין מחרוזות ניתן להשתמש באופרטורים ==, =! גם להשוואה בין מספרים אך ההשוואה תתבצע בין המחרוזות שמייצגות את המספרים –למה ישוערכו הביטויים הבאים ? 8 <= 08 8 >= 08 8 == 08 8 == 8 8 != 08 8 !~ 08 8 =~ 08 22
סיכום : אופרטורים בתוך משפטי if אופרטורים קבצים ותיקיותאופרטורים לעבודה עם קבצים ותיקיות : -f,-d אופרטורים לוגיים להרכבת תנאיםאופרטורים לוגיים להרכבת תנאים – !, &&, || כמו ב -C –ניתן להשתמש בסוגריים כמו ב -C if (($winner == "Yossi") || ($winner == "Einav")) then echo the Bublil family won ! endif 23
משפטי switch switch ( ) case : [breaksw] case : [breaksw]... case : [breaksw] [default: ] endsw 24 התאמת מחרוזות כמו באופרטור =~
משפטי switch: דוגמא switch($c) case "[a-z]": echo small letter breaksw case "[A-Z]": echo big letter breaksw case "[0-9]": echo digit breaksw case '$': echo dollar sign breaksw default: echo neither letter nor digit endsw 25
משפטי goto קפיצה למקוםמבצע קפיצה למקום המסומן ב - : כמו ב -Cכמו ב -C 26 goto goto goto error... error:... goto error... error:... גם ב C-Shell וגם ב -C שימוש ב -goto נחשב לתכנות רע ! משתמשים במנגנון goto רק כשכל האלטרנטיבות האחרות יותר גרועות
הפקודה printf printf format strings מדפיסה לפי הפורמטמדפיסה את המחרוזות strings לפי הפורמט format –הפורמט דומה לפורמט של הפקודה printf ב -C. תווי עריכההפורמט יכול להכיל תווים רגילים או תווי עריכה דוגמאות של תווי עריכה : – %s – %s - מדפיסה את המחרוזת המתאימה מתוך הרשימה strings. %[-]m[.n]s באורך של m הגבלת מספר התווים המודפסים ל - n מיושרת לימין - – - %[-]m[.n]s מדפיסה את המחרוזת המתאימה מרשימת המחרוזות כך שהתוצאה תהיה באורך של m תווים, עם אפשרות להגבלת מספר התווים המודפסים ( מתוך המחרוזת הספציפית ) ל - n. המחרוזת מיושרת לימין אלא אם משתמשים באופרטור -.
הפקודה printf - דוגמאות שימו לב מה קורה כאשר ישנן יותר מחרוזות ברשימה strings מאשר תווי עריכה (%s) > echo $HOME /home/rotics > > printf “My files are in %s\n“ $HOME My files are in /home/rotics > > printf “number is : %10.5s” a number is: > > printf “number is : #%-10.3s# %s\n” " a“ xxx number is: #123 # xxx > > printf “My files are in %s\n“ $HOME “my PC” My files are in /home/rotics My files are in my PC > echo $HOME /home/rotics > > printf “My files are in %s\n“ $HOME My files are in /home/rotics > > printf “number is : %10.5s” a number is: > > printf “number is : #%-10.3s# %s\n” " a“ xxx number is: #123 # xxx > > printf “My files are in %s\n“ $HOME “my PC” My files are in /home/rotics My files are in my PC
הרצת תסריטים להריץ בשתי דרכיםניתן להריץ תסריטים בשתי דרכים : הפקודה source –ע '' י הפקודה source מתבצע בסביבה הנוכחיתהתסריט מתבצע בסביבה הנוכחית ( ב -shell הנוכחי ) משתני הסביבה הנוכחיתיכול לשנות את משתני הסביבה הנוכחית ישירות – ישירות בסביבה חדשה משלוהתסריט מתבצע בסביבה חדשה משלו ( ב -shell חדש ) משתני הסביבה הנוכחיתלא יכול לשנות את משתני הסביבה הנוכחית נהוג בדרך השנייהאלא אם לשנות את משתני הסביבה הנוכחיתנהוג להריץ את התסריטים בדרך השנייה, אלא אם רוצים לשנות את משתני הסביבה הנוכחית 29
הרצת תסריטים ישירות הרשאת הרצהלפני שמריצים תסריט בפעם הראשונה חייבים לתת לו הרשאת הרצה > chmod u+x myscript להריץ בצורה ישירהאחרי שיש לקובץ הרשאת הרצה, ניתן להריץ אותו בצורה ישירה : > myscript –כמובן המשתנה path צריך להכיל את התיקיה הנוכחית, אחרת צריך להריץ בצורה הבאה : >./myscript 30
הרצת קבצי סקריפט איזה shell חדש להפעיל שורה ראשונהכדי שה shell- הנוכחי יידע איזה shell חדש להפעיל לצורך ביצוע התסריט, יש להוסיף לתסריט שורה ראשונה כתובת ה -shell המריץבמחשבים שונים כתובת ה -shell המריץ יכולה להיות שונה whichניתן לברר מהי באמצעות הפקודה which > which tcsh /bin/tcsh 31 #! /bin/tcsh -f כתובת ה-shell שיריץ את התסריט אומר ל-shell לא לבצע תסריטי אתחול ולהתחיל יותר מהר
תסריטי אתחול תסריטי אתחול מורצים אוטומטית בזמנים מסוימיםתסריטי אתחול ((setup הם תסריטים מיוחדים אשר מורצים אוטומטית ע " י המערכת בזמנים מסוימים. –.login עם כניסה לחשבון –.login מבוצע עם כניסה לחשבון –.cshrc בהתחלת הרצה –.cshrc מבוצע בהתחלת הרצה של כל shell( מסוג C-Shell) נהוג להשתמשנהוג להשתמש בהם התאמה אישית –להתאמה אישית של סביבת העבודה. למשל, אתחול משתני סביבה נחוצים לעבודה נתינת כינויים לפקודות (alias) משימות בצורה אוטומטית –לביצוע משימות שנרצה שיבוצעו בצורה אוטומטית בזמנים של כניסה לחשבון / פתיחת shell חדש 32
דוגמא לתסריט.cshrc 33 set path = ($path.) alias cdex2 cd ~mtm/public/0910a/ex2 alias gcc gcc -Wall -pedantic-errors -Werror set savehist=1000 set path = ($path.) alias cdex2 cd ~mtm/public/0910a/ex2 alias gcc gcc -Wall -pedantic-errors -Werror set savehist=1000
דוגמא לתסריט.login 34 # 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 # print a warning about Matam assignment set today = `date +%j` set assignment_day = 349 set days_in_this_year = 365 if( $today > $assignment_day) remaining_days = $assignment_day + ($days_in_this_year - $today) remaining_days = $assignment_day - $today endif date echo $remaining_days days until the submission of Matam assignment 2 ! # 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 # print a warning about Matam assignment set today = `date +%j` set assignment_day = 349 set days_in_this_year = 365 if( $today > $assignment_day) remaining_days = $assignment_day + ($days_in_this_year - $today) remaining_days = $assignment_day - $today endif date echo $remaining_days days until the submission of Matam assignment 2 !
העברת פרמטרים לתסריטים להעביר פרמטריםניתן להעביר פרמטרים לתסריטים בדומה להעברת פרמטרים לתוכנית C –ב -C ניתן להתייחס לפרמטרים ע '' י מערך argv בתסריט C-Shell ניתן להתייחס לפרמטרים בצורה הבאה : – $0 – $0 - הפקודה עצמה – ${n} ${argv[n]} – ${n} או ${argv[n]} - הפרמטר ה -n – $* – $* - רשימת כל הפרמטרים – ${#argv} – ${#argv} - מספר הפרמטרים 35
דוגמא : echo_script 36 #! /bin/tcsh -f echo command: $0 set number = 1 foreach param ( $* ) echo parameter $number : number++ end #! /bin/tcsh -f echo command: $0 set number = 1 foreach param ( $* ) echo parameter $number : number++ end > echo_script aaa bbb ccc command:./echo_script parameter 1 : aaa parameter 2 : bbb parameter 3 : ccc > echo_script aaa bbb ccc command:./echo_script parameter 1 : aaa parameter 2 : bbb parameter 3 : ccc
קלט בשפת C-Shell : אופרטור $< $<אופרטור $< –גורם לשורה שלמה להיקרא מערוץ הקלט הסטנדרטי set line = “$<“ שורה שלמה אחת תיקרא מערוץ הקלט הסטנדרטי ותושם למשתנה line בתור מחרוזת ( כולל רווחים ) –נהוג לבצע ישר המרה לרשימה על ידי שימוש ב -() set line = ($<) השורה תופרדותושםהשורה מהקלט הסטנדרטי תופרד למילים ותושם למשתנה line בתור רשימה אחרי הביצוע של השורה הזאת ניתן לבצע פעולות רגילות של C-Shell על רשימות : $line[1], shift, ${#line}, $line[3-] וכו ' אין דרך טבעית לקרוא מקבציםאין דרך טבעית וישירה לקרוא מקבצים ב -C-Shell –רק מהקלט הסטנדרטי 37
חלוקה פונקציונאלית של תסריטים לחלק למודולים ופונקציותבשפת C למדנו לחלק תוכניות למודולים ופונקציות קריאותשימוש חוזר –לשיפור קריאות, שימוש חוזר בקוד וכו ' אין פונקציותבשפת C-Shell אין פונקציות " התסריט הראשי " " תסריטי עזר " –מחלקים תסריט ל " התסריט הראשי " שמשתמש ב " תסריטי עזר " –כל " תסריט עזר " הוא תסריט בפני עצמו ניתן להריץ אותו בנפרד הוא יכול להשתמש בתסריטים ותוכנות אחרות 38
תסריטים : העברת פרמטרים בשורת הארגומנטיםבשורת הארגומנטים helper_script aaa bbb 17 ב -pipelineב -pipeline לתוך הערוץ הקלט הסטנדרטי echo aaa bbb 17 | helper_script קובץ זמנידרך קובץ זמני echo aaa bbb 17 > tmp helper_script < tmp 39
תסריטים : ערכי חזרה backticksעל ידי backticks set result = `helper_script aaa bbb 17` ב -pipelineהעברה לתסריט אחר ב -pipeline helper_script aaa bbb 17 | another_script קובץ זמנידרך קובץ זמני helper_script aaa bbb 17 > tmp 40
קלט מקבצים כאמור, אין דרך טבעית קלט מקבציםכאמור, אין ב -C-shell דרך טבעית וישירה לקרוא קלט מקבצים אופרטור $< –הדרך הטבעית היא לקרוא שורות מערוץ הקלט הסטנדרטי על ידי אופרטור $< לכן משתמשים בשיטה הבאה : –מחלקים לשני תסריטים –מחלקים את משימת קריאת הקלט לשני תסריטים : " התסריט הראשי " " תסריט העזר " תוכן הקובץ ב -pipeline –התסריט הראשי ישפוך את תוכן הקובץ ב -pipeline לתסריט העזר : cat file | helper_script יחבר את הקובץ הקלט הסטנדרטי –או יחבר את הקובץ ישירות לערוץ הקלט הסטנדרטי : helper_script < file תוכן הקובץ הקלט הסטנדרטיתוכן הקובץ יועבר לערוץ הקלט הסטנדרטי של תסריט העזר יקרא מהקלט הסטנדרטי –תסריט העזר יקרא מהקלט הסטנדרטי על ידי אופרטור $< 41
דוגמא נתון קובץ המכיל נתונים על שערים שהובקעו במשחקי כדורגל.נתון קובץ football המכיל נתונים על שערים שהובקעו במשחקי כדורגל. כל שורה בקובץ מציינת, שהבקיע במשחק שנערך ב מסוים, בה הוא שיחק.כל שורה בקובץ מציינת שם של שחקן, מספר השערים שהבקיע במשחק שנערך בתאריך מסוים, שם הקבוצה בה הוא שיחק ושם הקבוצה היריבה. 42 >cat football 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 >cat football 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
דוגמא ברצוננו לכתוב תסריט בשם player. התסריט פרמטר שם מלא –יקבל כפרמטר שם מלא של שחקן ידפיס השורות מופיע שם השחקן – ידפיס את כל השורות של הקובץ football בהן מופיע שם השחקן ידפיססכום מספר השערים – ובנוסף ידפיס את סכום מספר השערים שהוא הבקיע. לדוגמא, הפלט עבור שורת הקלט Alon Miz. יהיה : 43 > 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 > 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
פתרון בתסריט player לא נוכל לבצע קריאת קלט מהקובץ football ניעזר בתסריט אחר –ולכן ניעזר בתסריט אחר בשם calc_total ישפוך את השורות ב -pipeline –התסריט player ישפוך את השורות שבהם מופיע השחקן ב -pipeline ל - calc_total יקרא את שורות ידי אופרטור $< – calc_total יקרא את שורות שבהם מופיע השחקן מערוץ הקלט הסטנדרטי על ידי אופרטור $< 44
פתרון 45 > cat calc-total #! /bin/tcsh -f set line = ($<) set sum = 0 while (${#line} != sum = $sum + $line[3] echo $line set line = ($<) set line = ($<)end echo "total number of goals: $sum" > cat calc-total #! /bin/tcsh -f set line = ($<) set sum = 0 while (${#line} != sum = $sum + $line[3] echo $line set line = ($<) set line = ($<)end echo "total number of goals: $sum" > cat player #! /bin/tcsh -f grep "$1" football | calc-total > cat player #! /bin/tcsh -f grep "$1" football | calc-total בפונט מודגש : התבנית הכללית של עיבוד הקלט
דוגמא נוספת תסריט לדירוג שחקניםעלינו לכתוב תסריט לדירוג שחקנים בשם scores –השמותמועברים כפרמטרים –השמות המלאים של השחקנים מועברים כפרמטרים בשורת הפקודה –הדירוגמספר השערים הנתונים המוכלים בקובץ –הדירוג של כל שחקן ייקבע על פי מספר השערים שהוא הבקיע לפי הנתונים המוכלים בקובץ football שני שחקנים שהבקיעו מספר זהה של שערים יקבלו דירוג זהה. ידפיס דירוגו שמו המלא מספר השעריםהתסריט ידפיס עבור כל שחקן את דירוגו, את שמו המלא ואת מספר השערים שהבקיע 46
תזכורת : קובץ football 47 >cat football 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 >cat football 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
דוגמא להפעלת התסריט 48 > scores "Alon Miz." "Izak Zoh." "Ronen Ha." "Reuven A." 1 Alon Miz. 6 1 Ronen Ha. 6 2 Izak Zoh. 4 3 Reuven A. 2 > scores "Alon Miz." "Izak Zoh." "Ronen Ha." "Reuven A." 1 Alon Miz. 6 1 Ronen Ha. 6 2 Izak Zoh. 4 3 Reuven A. 2
פתרון 49 > cat scores #! /bin/tcsh i = 1 while ( $i <= ${#argv} ) grep "${argv[$i]}" football | calc_score >>! temp grep "${argv[$i]}" football | calc_score >>! i++end sort -n -k 3 -r temp | calc_place if (-f temp) then rm -f temp rm -f tempendif > cat scores #! /bin/tcsh i = 1 while ( $i <= ${#argv} ) grep "${argv[$i]}" football | calc_score >>! temp grep "${argv[$i]}" football | calc_score >>! i++end sort -n -k 3 -r temp | calc_place if (-f temp) then rm -f temp rm -f tempendif
פתרון 50 > cat calc_place #! /bin/tcsh -f set line = ($<) set place = goals = $line[3] while (${#line} != 0) if ($goals != $line[3]) goals = $line[3] endif echo "$place $line" set line = ($<) end > cat calc_place #! /bin/tcsh -f set line = ($<) set place = goals = $line[3] while (${#line} != 0) if ($goals != $line[3]) goals = $line[3] endif echo "$place $line" set line = ($<) end > cat calc_score #! /bin/tcsh -f set line = ($<) set sum = 0 set player_name = ($line[1-2]) while (${#line} != sum = $sum + $line[3] set line = ($<) end echo "$player_name $sum" > cat calc_score #! /bin/tcsh -f set line = ($<) set sum = 0 set player_name = ($line[1-2]) while (${#line} != sum = $sum + $line[3] set line = ($<) end echo "$player_name $sum"
C-shell לעומת C שפת תסריטים scripting languageשפת C-shell היא שפת תסריטים (scripting language) –קיימות שפות תסריטים מתקדמות יותר : Perl, Tcl, PHP, JavaScript, Python, Ruby מזל טוב ! למדתם שפת התסריטים הראשונה שלכם !מזל טוב ! למדתם שפת התסריטים הראשונה שלכם ! 51
C-shell לעומת C שפת תכנות מערכת system languageשפת C היא שפת תכנות מערכת (system language) –קיימות שפות תכנות מערכת מתקדמות יותר : C++, Java, C# 52
יתרונות של C-shell לעומת C קל להריץ תוכניותקל להריץ תוכניות אחרות –להעביר פרמטרים –לשלב פלט של תוכניות –לשלב בין תוכניות –יתרון גדול בסביבת Unix שבה יש הרבה תוכניות סטנדרטיות (sort, grep,cut) קבציםעבודה נוחה עם קבצים מחרוזותעבודה נוחה עם מחרוזות משתנים ותסריטי עזרעבודה נוחה עם משתנים ותסריטי עזר –לא צריך להגדיר טיפוסים, להכריז על משתנים ופונקציות לפתח בזמן קצר יותרניתן לפתח תוכניות בזמן קצר יותר ! בשפת תסריטים קצרה יותר –תוכנית שכתובה בשפת תסריטים יכולה להיות פי 5 קצרה יותר מאותה התוכנית שכתובה בשפת C 53
חסרונות של C-shell לעומת C פחות בטיחותיתהשפה פחות בטיחותית - קל להכניס באגים –אין בדיקות טיפוסים –לא חייבים להגדיר משתנים לפני השימוש בהם –לדוגמא, איפה הבאג בקוד הבא ? מה יודפס בסוף הריצה שלו ? 54 set deposits = ($*) set account_balance = 100 foreach d acount_balance = $account_balance + $d end echo $account_balance
חסרונות של C-shell לעומת C זמן ביצוע פי כמה מאות ארוך יותרזמן ביצוע של תוכנית שכתובה ב -C-shell יכול להיות פי כמה מאות ארוך יותר לעומת אותה התוכנית שכתובה ב -C 55
שימוש ב -C-shell לעומת C משתמשים ב -C-shell כאשר –זמן ביצוע לא קריטי למשל כאשר המשימה מספיק קטנה כך שזמן הביצוע לא מורגש –איכות התוכנה לא קריטית או שהתכנית מספיק קטנה כדי שיהיה אפשר למצוא בה את כל הבאגים בצורה קלה משתמשים ב -C כאשר –זמן ביצוע חשוב –איכות התוכנה –איכות התוכנה היא קריטית 56
בקרת תהליכים ב -Unix
תהליכים ב -Unix מספר רב של משתמשים בו זמנית Unix היא מערכת הפעלה המסוגלת לשרת מספר רב של משתמשים בו זמנית בו זמנית מספר רב של תהליכים –כל משתמש יכול להריץ בו זמנית מספר רב של תהליכים תהליךניתן לראות תהליך כהרצה של תוכנית כלשהי –יכולים להתקיים במקביל מספר תהליכים שכולם מריצים את אותה התוכנית תהליך יכול –ליצור –ליצור תהליכים נוספים –להרוג –להרוג תהליך שיצר –לשלוח הודעות –לשלוח הודעות לתהליכים אחרים 58
תהליכים בקורס מת '' מ במת '' מ לא נלמד כיצד תהליכים מבצעים את כל הפעולות הנ " ל –נשאיר זאת לקורס במערכות הפעלה משתמש –נלמד כיצד משתמש יכול ליצורליצור מספר תהליכים לשלוטלשלוט על אופן ביצועם להרוגלהרוג תהליכים 59
מצבים של תהליכים בחזית foregroundריצה בחזית (foreground) תהליך אחד –רק תהליך אחד יכול לרוץ בחזית לקרוא מהמקלדת –רק התהליך בחזית יכול לקרוא מהמקלדת ה -prompt נעלם –כשהמשתמש מריץ תהליך בחזית ה -prompt נעלם עד סיום התהליך לא ניתן להריץ פקודות נוספות ברקע backgroundריצה ברקע (background) מספר תהליכים בו זמנית –ברקע יכולים לרוץ מספר תהליכים בו זמנית לא יכול לקרוא מהמקלדת –תהליך שרץ ברקע לא יכול לקרוא מהמקלדת ה -prompt חוזר –כשהמשתמש מריץ תהליך ברקע ה -prompt חוזר ניתן להריץ פקודות נוספות השעיההשעיה נעצר –התהליך נעצר עד שיעבירו אותו למצב ריצה 60
יצירת תהליכים הקשת שם של התוכניתיוצרים תהליכים על ידי הקשת שם של התוכנית להרצה בשורת הפקודה : –בחזית –ברקע 61 > command & > command2 & > command& > > command & > command2 & > command& > > command
בדיקת מצב תהליכים jobsהפקודה jobs מספרי תהליך –המספרים בסוגריים מרובעים מציינים מספרי תהליך מזהים תהליכים בשביל הפקודות לטיפול בתהליכים התהליך ה " נוכחי " –סימן ה -"+" מייצג את התהליך ה " נוכחי " ברירת המחדלברירת המחדל לפקודות לטיפול בתהליכים 62 >jobs [1] + Running command [2] - Running command2 [3] Running command >jobs [1] + Running command [2] - Running command2 [3] Running command
השעיית תהליך הפקודה –משעה –משעה את התהליך שמספרו jobID משעה התהליך בחזיתהקשת Ctrl-z - משעה את התהליך בחזית 63 stop stop [%jobID] > command Ctrl-z [1] + Suspended command < > command Ctrl-z [1] + Suspended command < >jobs [1] + Running command [2] - Running command2 > stop %1 >jobs [1] + Suspended (signal) command [2] - Running command2 >>jobs [1] + Running command [2] - Running command2 > stop %1 >jobs [1] + Suspended (signal) command [2] - Running command2 >
העברת תהליך לחזית הפקודה –מעבירה לחזית –מעבירה את התהליך שמספרו jobID לחזית 64 fg [%jobID] fg [%jobID] > more try_input.c main(){ char str[20]; char str[20]; printf("I shall try to eat something"); printf("I shall try to eat something"); scanf(“%s", str); scanf(“%s", str); printf(“Ate %s", str); printf(“Ate %s", str);} > more try_input.c main(){ char str[20]; char str[20]; printf("I shall try to eat something"); printf("I shall try to eat something"); scanf(“%s", str); scanf(“%s", str); printf(“Ate %s", str); printf(“Ate %s", str);} > try_input& [1] 828 > I shall try to eat something [1] + Suspended (tty input) try_input > jobs [1] + Suspended (tty input) try_input > fg %1 try_inputcookies Ate cookies > > try_input& [1] 828 > I shall try to eat something [1] + Suspended (tty input) try_input > jobs [1] + Suspended (tty input) try_input > fg %1 try_inputcookies Ate cookies >
העברת תהליך לרקע הפקודה –מעבירה לרקע –מעבירה את התהליך שמספרו jobID לרקע 65 bg [%jobID bg [%jobID] >jobs [1] + Suspended (signal) command [2] - Running command2 > bg %1 >jobs [1] Running command [2] + Running command2 >>jobs [1] + Suspended (signal) command [2] - Running command2 > bg %1 >jobs [1] Running command [2] + Running command2 >
הריגת תהליך הפקודה –הורגת –הורגת את התהליך שמספרו jobID הורגת התהליך בחזיתהקשת Ctrl-c - הורגת את התהליך בחזית 66 kill -9 %jobID > command Ctrl-c< Ctrl-c< >jobs [1] + Running command [2] - Running command2 > kill -9 %2 >jobs [1] + Running command [2] Terminated command2 >>jobs [1] + Running command [2] - Running command2 > kill -9 %2 >jobs [1] + Running command [2] Terminated command2 >
תרשים המצבים של תהליך 67 חזיתחזית רקערקע השעיההשעיה סיוםסיום Ctrl-z Ctrl-c fg fg stop kill kill bg
68