1 / 53

תרגול מס' 6

תרגול מס' 6. שרשור פקודות באמצעות Pipeline עבודה ב- C-Shell כתיבת תסריטים ב- C-Shell. Pipeline. הרכבת פקודות Pipeline. הרכבת פקודות. נניח שברצוננו להדפיס את התוכן של תיקיה המכילה הרבה קבצים לא נוכל במצב זה לראות את כל הקבצים

hollis
Télécharger la présentation

תרגול מס' 6

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. תרגול מס' 6 שרשור פקודות באמצעות Pipeline עבודה ב-C-Shell כתיבת תסריטים ב-C-Shell

  2. Pipeline הרכבת פקודות Pipeline מבוא לתכנות מערכות - 234122

  3. הרכבת פקודות • נניח שברצוננו להדפיס את התוכן של תיקיה המכילה הרבה קבצים • לא נוכל במצב זה לראות את כל הקבצים • נוכל להשתמש בהפנית פלט הפקודה ls לקובץ זמני ולאחר מכן שימוש ב-more: > ls -l > tmp > more < tmp > rmtmp מבוא לתכנות מערכות - 234122

  4. Pipeline • כדי לחסוך את הבלגן שבטיפול בקבצים זמניים ניתן להשתמש ב-pipeline המחבר את הפלט של פקודה אחת לקלט של פקודה שניה ישירות • כדי לחבר שתי פקודות כך נרשום אותן אחת אחרי השניה כאשר ביניהן מפריד התו ‘|’ • על מנת לראות בשלבים את התוכן של תיקיה גדולה נוכל לרשום כעת: > ls -l | more • ניתן לשלב מספר תכניות בבת אחת: > command1| command2| command3 command1 command2 command3 stdout stdin stdout stdin מבוא לתכנות מערכות - 234122

  5. Pipeline - סיכום • ניתן להשתמש בתו ‘|’ כדי לחבר את הפלט של תכנית א' עם הקלט של תכנית ב' • בעזרת pipeline נוכל להרכיב פקודות מורכבות בעבודה בטרמינל מתכניות פשוטות מבוא לתכנות מערכות - 234122

  6. עבודה ב-C-Shell מהו C-Shell? תכונות מתקדמות של C-Shell עבודת ה-C-Shell מבוא לתכנות מערכות - 234122

  7. Shell • Shell (קליפה) הוא כינוי לתוכנה המקשרת בין המשתמש לבין גרעין מערכת ההפעלה • בדרך כלל המונח בשימוש עבור shell טקסטואלי • כאשר אנו מתחברים ל-stud נפתחת shell ברירת המחדל עבור מחשב זה -C-Shell • דוגמאות נוספות ל-shell: • bash (ברירת המחדל ברוב הפצות הלינוקס) • powershell (shell מתקדם עבור windows) • מלבד מנשק בסיסי לביצוע פקודות ה-Shellמקל עלינו את העבודה בעזרת תכונות מתקדמות, לדוגמה ההשלמה האוטומטית המתבצעת ע"י לחיצה על Tab מבוא לתכנות מערכות - 234122

  8. C-Shell • נשתמש בגרסה מורחבת של C-Shell הקרויה tcsh (Tenex C-Shell) • במחשבים בהם זהו אינו Shell ברירת המחדל ניתן להפעילו פשוט על ידי הרצת הפקודה tcsh • ניתן להשתמש בפקודה הבאה כדי לקבל את שם ה-Shell הנוכחי ב-Unix > echo $0 tcsh • עבודת ה-Shell מתבצעת על ידי קבלת פקודה מהמשתמש, ביצוע החלפות טקסט בפקודה בהתאם לתכונות ה-Shell ולבסוף שליחת הפקודה המעובדת למערכת ההפעלה • ה-Shell יאפשר לנו להגדיר קיצורים, לחזורעל פקודות, להתייחס למספר קבצים בנוחות ולהגדיר משתניםאשר נוכל להשתמש בהם בפקודות מבוא לתכנות מערכות - 234122

  9. הפקודה echo • במקרים רבים נרצה להדפיס לפלט מחרוזת, לשם כך ניתן להשתמש בפקודה echo • הפקודה echoמדפיסה את הפרמטרים שקיבלה > echo [-n] [words] • -n: מדפיס ללא ירידת שורה > echo Hello world! Hello world! מבוא לתכנות מערכות - 234122

  10. נתינת כינויים לפקודות - alias • הפקודה alias מאפשרת להגדיר קיצורים ב-Shell > alias <new name> <command + parameters> • לאחר הרצת הפקודה נוכל לרשום את הפקודה <new name> כקיצור לפקודה <command> עם הפרמטרים שהוספנו. • כדי לבטל aliasניתןלהשתמש בפקודהunalias <alias> • ה-Shell יבדוק בשלב עיבור הפקודה האם המילה הראשונה היא alias ואם כן יבצע החלפה מתאימה < alias llls -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 GCC: Command not found. מבוא לתכנות מערכות - 234122

  11. Filename Expansion • ניתן לרשום בפקודה תבנית המתייחסת למספר קבצים. במקרה זה C-Shell יחליף את מחרוזת התבנית בפקודה ברשימת הקבצים המתאימים לתבנית • הסימן * מתאים למחרוזת כלשהי (כולל ריקה) • הסימן ? מתאים לתו כלשהו יחיד • ניתן להתייחס למספר תווים אפשריים על ידי שימוש ב-[ ] • ניתן לרשום את התווים האפשרייםאחד אחרי השני במפורש • ניתן לרשום טווח של תווים, למשל 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

  12. משתנים • ניתן להציב ערך למשתנה ב-C-Shell על ידי הפקודה set > set <varname>=<value> • אין צורך להכריז על משתנים ב-C-Shell, לאחר ביצוע השמה למשתנה הוא מוגדר אוטומטית • ניתן להחליףערך של משתנה על ידי פקודת set נוספת • ניתן לקרוא משתנים על ידי שימוש באופרטור $, למשל: > echo $<varname> • השימוש במשתנה הוא פשוט החלפת הקריאה למשתנה בערך השמור בו מבוא לתכנות מערכות - 234122

  13. משתנים • ניתן לבטל הגדרה של משתנה על ידי הפקודה unset <varname> < unset my_variable • בדרך כלל אין צורך בכך • אם מנסים לקרוא משתנה שאינו מוגדר מתקבלת שגיאה > echo $blahblah blahblah: Undefined variable. • ניתן להשתמש ב-{} כדי לסמן מהו שם המשתנה לאופרטור $ • מועיל כאשר השימוש במשתנה צמוד למחרוזת נוספת > set a=Hell > echo $ao ao: Undefined variable. > echo ${a}o Hello מבוא לתכנות מערכות - 234122

  14. משתנים - רשימות • ניתן לשמור במשתנה יחיד רשימהשל מחרוזות על ידי שימוש בסוגריים > set list=(1 2 3) • קריאת משתנה תחליף אותו בתוכן כל הרשימה (הסוגריים אינם נשמרים) > echo $list1 2 3 • ניתן לגשת לאיבר יחיד בעזרת אופרטור [ ] • מספור האינדקסים מתחיל מ-1! • חריגה מהטווח הרשימה תגרום לשגיאה > echo $list[1]1 • ניתן לגשת לתחומים מהרשימה > echo A:$list[-2] B:$list[2-] C:$list[1-2]A:1 2 B:2 3 C:1 2 • ניתן לקבל את מספר האיברים ברשימה בעזרת $#<varname> > echo $#list3 מבוא לתכנות מערכות - 234122

  15. משתנים - רשימות • לא ניתן לשמור ב-C-Shell רשימות מקוננות > set list[1]=(1 2) set: Syntax error • ניתן לשמור מחרוזות המכילות רווחים בעזרת שימוש בגרשיים כפולים > set list=(Matam "Hello world" 17) > echo $#list : $list 3 : Matam Hello world 17 > echo $list[2] Hello world • השמת מחרוזות לרשימה ללא גרשיים תגרום לאיבוד הרווחים המדויקים שהיו בין המילים > set str=" Very crazy spaces " > set list=($str) > echo $list Very crazy spaces מבוא לתכנות מערכות - 234122

  16. משתנים - רשימות • ניתן להתייחס למשתנה רגיל כאל רשימה בעלת איבר יחיד > set a=Hello > echo $a[1] Hello > set str="Hello world" > echo $str[2] str: Subscript out of range. > set list=(Hello world) > echo $str[2] world • מה קורה בפקודה הבא? מדוע? כיצד יש לתקן אותה? > set list=$list מבוא לתכנות מערכות - 234122

  17. משתנים - ערכים מספריים • בניגוד לשפת C, למשתנים ב-C-Shell אין טיפוס. כל המשתנים הם מסוג רשימה של מחרוזות • הפקודה @ מבצעת פעולות חשבוניות על מחרוזת המכילות ערכי מספרים חוקיים ומציבה את התוצאה למשתנה • המשתנה יכול להיות לא מוגדר לפני הפקודה (כמו ב-set) > @ n = 3 + 4 > echo $n 7 > set a = 5 > @ b = 7 > @ sum = $a + $b > echo $sum 12 מבוא לתכנות מערכות - 234122

  18. משתנים - פעולות חשבוניות • ניתן לבצע את הפעולות הבאות בעזרת @: • פעולות חשבוניות פשוטות: +, -, * ו-/ • השמות: = • הגדלות והקטנות: +=, -=, -- ו-++ (אין משמעות ל-pre ו-post) • ניתן להוסיף סוגריים, שימו לב שהאסוציאטיביות אינה סטנדרטית • הפקודה @ רגישה לרווחים, הקפידו לשיםרווח בין כל מספר לאופרטור • עבור פעולות ההשמה לא חובה להוסיף רווח • אם מנסים לבצע פעולות על ערכים לא מספרייםתתקבל שגיאה • ניתן לבצע פעולות חשבוניות רק על מספרים שלמים > @ mistake = 3 - 4 + 5 > echo $mistake -6 > @ n = 3+4 @: Badly formed number. > set str=Hello > @ n = 3 + $str @: Badly formed number. > @ n = 3.3 @: Badly formed number. למה צריך רווח אחרי ה-@? מבוא לתכנות מערכות - 234122

  19. היסטוריה • C-Shell שומר את הפקודות האחרונות שהתבצעו ומאפשר ביצוען מחדש • הדרך הכי פשוטה לגשת להיסטוריה היא על ידי שימוש ב-↑ ו-↓ • ניתן לראות את הפקודות האחרונות שבוצעו על ידי הפקודה history • ניתן לבצע את האחרונה על ידי !! • ניתן לבצע את פקודה מספר על ידי ! • ניתן לבצע את הפקודה האחרונה שהתחילהב-<string> על ידי !<string> • מספר הפקודות שיישמרו מוגדר על ידיהמשתנה history > history 1 17:20 set a = 3 2 17:21 set b = 4 3 17:22 @ n = $b + $a 4 17:24 echo $n 5 17:28 history > !4 echo $n 7 > !! echo $n 7 > !set set b = 4 החלפות המתבצעות בגלל גישה להיסטוריה מודפסות בזמן ביצוען ולפני ביצוע הפקודה מבוא לתכנות מערכות - 234122

  20. Command Substitution • ניתן "לשרשר" פקודות על ידי שימוש בגרשיים הפוכים ` • באנגלית: backticks או backquotes • C-Shell יבצע תחילה את הפקודה בתוך ` ` ויחליף אותה בטקסט שהודפס על ידיה > echo The length of $str is `echo -n $str | wc -c` The length of Hello is 5 > grep 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

  21. סוגי גרשיים • גרשיים כפולים, " ", משמשים לשמירה על רווחים • בתוך גרשיים כפולים לא תתבצענה החלפות עבור תבניות של שמות קבצים > echo "*.c" : *.c *.c : a.chello.c • משתמשים ב-" " כאשר יש צורך לשמור מחרוזות שלמות במדויק > set sentence="The dingo ate your baby" • גרשיים בודדים ' ', מונעים את כל החחלפות בתחומם > echo lets make some '$$$' lets make some $$$ • גרשיים הפוכים (backticks) מבצעים command substitution מבוא לתכנות מערכות - 234122

  22. סוגי גרשיים • התוצאה המוחזרת מהפעלת פקודה ב-backticks מוחזרת כרשימה • עבור שימוש רגיל ב-backticksכל רווח, טאב או ירידת שורה יפרידו בין איברים ברשימה המתקבלת • אם ה-backticksבתוך " " רק ירידת שורה תפריד בין איברים > set a = `cat lines` > echo $#a 4 > echo 1:$a[1] 2:$a[2] 1:a 2:b > set a = "`cat lines`" > echo $#a 2 > echo 1:$a[1] 2:$a[2] 1:a b 2:c d line a b c d מבוא לתכנות מערכות - 234122

  23. עבודת ה-shell • עבודת ה-Shell מתבצעת בלולאה: • הצגת prompt • המתנה לפקודה • עיבוד הפקודה עד לקבלת פקודה פשוטה • ביצוע הפקודה • לשם כך C-Shell מנהל מבני נתונים פנימיים אשר שומרים את ההיסטוריה, המשתנים וה-aliasesשהוגדרו • הטיפול בפקודה מתבצע בשלושה שלבים עיקריים • ניתוח הפקודה: הפקודה מופרדת למילים על פי רווחים וטאבים. התווים |,< ו-> מפרידים בין פקודות • עיבוד הפקודה:ביצוע החלפות מחרוזות הפקודה עד לקבלת פקודה פשוטה • ביצוע הפקודה: שליחת הפקודה הפשוטה שהתקבלה על ידי מערכת ההפעלה מבוא לתכנות מערכות - 234122

  24. עיבוד הפקודה • בשלב זה מבצע C-Shell החלפות במחרוזת הפקודה עד לקבלת פקודה פשוטה: • אם הפקודה מכילה שימוש בפקודות קודמות (ע"י שימוש בסימן !) מתבצעת החלפה מההיסטוריה ומודפסת שורת הפקודה שנבחרה מההיסטוריה • אם המילה הראשונה בפקודה הינה aliasמתבצעת החלפה לפי ה-alias המוגדר • החלפת ביטויים המתחילים ב-$ בערכי המשתנים המתאימים • החלפת תבניות של שמות קבצים ברשימת הקבצים המתאימה • החלפת פקודות המופיעות בתוך גרשיים הפוכים בתוצאת הפקודה • אם באחד השלבים מתרחשת שגיאה העיבוד ייעצר ותודפס הודעה מתאימה מבוא לתכנות מערכות - 234122

  25. ביצוע הפקודה • לאחר שהתקבלה פקודה סופית על C-Shell להפעיל את הפקודה המתאימה, הפקודות מתחלקות שני סוגים: • פקודות פנימיות של ה-Shell, למשל cd, set, unset, @... • פקודות חיצוניות - שמות קבצי הרצה, למשל ls, gcc, cat, sort... • אם שם הפקודה מתאים לפקודה פנימית היא תיבחר • אחרת ה-Shell יחפש בכל התיקיות המופיעות במשתנה pathקובץ הרצה בשם המתאים • אם נרצה לאפשר ל-Shell להריץ תכניות מהתיקיה הנוכחית ללא שימוש ב-‘.’ניתן להוסיף את התיקיה הנוכחית ל-path. • ניתן להשתמש בפקודה whichכדי לגלותאיזו תכנית תופעל עבור שם פקודה מסוים > set path=($path .) > hello Hello world! > which hello /usr/username/progs/hello > which gcc /usr/bin/gcc < which cd cd: shell built-in command. מבוא לתכנות מערכות - 234122

  26. עבודה ב-C-Shell - סיכום • ל-C-Shell מגוון תוכנות מתקדמות המאפשרות למשתמש מתקדם לבצע פעולות מסובכות בקלות • ניתן להתייחס למספר קבצים בבת אחת על ידי שימוש בתבניות • ניתן להגדיר כינויים לפקודות ופרמטרים שכיחים בעזרת alias • ניתן לקרוא לפקודות שהתבצעו בעבר הקרוב בעזרת ההיסטוריה • ניתן לשמור ערכים במשתנים ולנצלם לפקודות ב-C-Shell • כל המשתנים ב-C-Shell הם מסוג רשימות של מחרוזות • ניתן להשתמש ב-` ` כדי לבצע החלפת פקודה בפלט שלה בשורות פקודה ב-C-Shell • כל התכונות של C-Shell מבוצעות על ידי החלפת מחרוזות פשוטה בשלב עיבוד הפקודה מבוא לתכנות מערכות - 234122

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

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

  29. הרצת תסריט בעזרתsource • ניתן להריץ קובץ המכיל פקודות C-Shell (להלן תסריט - 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) >&! tmperr diff expout1 tmpout diff experr1 tmperr echo Running test 2 (mtm_rentals < test2.in >! tmpout) >&! tmperr diff expout1 tmpout diff experr1 tmperr echo Running test 3 (mtm_rentals < test3.in >! tmpout) >&! tmperr diff expout1 tmpout diff experr1 tmperr מבוא לתכנות מערכות - 234122

  30. תסריטי אתחול • בהתחברות של משתמש למערכת מורץ התסריט .login אשר בתיקית הבית של המשתמש • בפתיחת C-Shell חדש מורץ התסריט .cshrc • הרצות תסריטי האתחול מתבצעות באמצעות source, ולכן הן משפיעות על מצב ה-Shell .cshrc .login set path = ($path .) set savehist=1000 alias llls-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

  31. הרצת תסריט כקובץ הרצה • ניתן להריץ תסריט כפקודה: • בתחילת התסריט יש להוסיף את השורה #!/bin/tcsh -f • #! מסמן ל-Unix שהשורה הראשונה בקובץ מגדירה את התכנית לביצוע שאר הפקודות בקובץ • /bin/tcshהוא שם התכנית לביצוע הפקודות, במקרה שלנו C-Shell • -fמונע מה-Shell להריץ תסריטי אתחול • בנוסף יש להוסיף הרשאת ריצה לקובץ • כעת ניתן להריץ את התסריט כמו תכנית רגילה • בניגוד להרצה באמצעות פקודת source התסריט יבוצע בתהליך Shell חדש אשר יסתיים בסוף ריצת התסריט מבוא לתכנות מערכות - 234122

  32. הרצת תסריט כקובץ הרצה • נמיר את תסריט הרצת הבדיקות שלנו לקובץ הרצה: • בעיה חדשה: התסריטמתחיל להסתבך, הוספתבדיקות נוספות משכפלתקוד בתסריט ולא נוחה (ייתכנו אלפי בדיקות) • פתרון: נשתמש במבני בקרה (תנאים ולולאות) בדומה לשפת C > chmoda+xrun_tests > ./run_tests Running test 1 Running test 2 Running test 3 run_tests #!/bin/tcsh -f echo Running test 1 (mtm_rentals < test1.in >! tmpout) >&! tmperr diff expout1 tmpout diff experr1 tmperr echo Running test 2 (mtm_rentals < test2.in >! tmpout) >&! tmperr diff expout1 tmpout diff experr1 tmperr echo Running test 3 (mtm_rentals < test3.in >! tmpout) >&! tmperr diff expout1 tmpout diff experr1 tmperr מבוא לתכנות מערכות - 234122

  33. while • ניתן ליצור לולאות whileב-C-Shell: while (<expression>)<command1><command2>...end • הפקודות בגוף הלולאה יבוצעו כל עוד <expression> ממשיך להתקיים • לולאות while כמו שאר מבני הבקרה ניתנות לביצוע ישירותמהטרמינל > set i=1 > while ($i <= 3) while? echo $i while? @ i++ while? end 1 2 3 > ./run_tests Running test 1 Running test 2 Running test 3 run_tests #!/bin/tcsh -f set i=1 while ($i <= 3) echo Running test $i (mtm_rentals < test$i.in \ >! tmpout) >&! tmperr diff expout$itmpout diff experr$itmperr end מבוא לתכנות מערכות - 234122

  34. foreach • לולאת foreach משמשת למעבר על רשימה בצורה נוחה foreach <varname> (<list>) <command1> <command2> ...end • <varname> הוא שם המשתנה שיכיל בכל פעם איבר מהרשימה • <list> היא רשימה של מחרוזות run_tests #!/bin/tcsh -f foreach test (test*.in) echo Running $test (mtm_rentals < $test >! tmpout) >&! tmperr diff expout_$test tmpout diff experr_$test tmperr end > ./run_tests Running test1.in Running test2.in Running test3.in מבוא לתכנות מערכות - 234122

  35. if • ניתן להגדיר ב-C-Shell משפטי תנאי בשתי גרסאות • בשורה יחידה ללא else: if (<expression>) <command> • עבור בלוקים של פקודות (עם אפשרות ל-else): if (<expression>) then[commands] [else[more commands] ]endif מבוא לתכנות מערכות - 234122

  36. ביטויים אפשריים ב-if ו-while • השוואת מחרוזותעל ידי == ו-=! • השוואת ערכים מספריים על ידי =>, =<, >, < • אם אחד הפרמטרים לאופרטור אינו ערך מספרי תתקבל שגיאה • התנאי -f <filename>בודק האםקיים קובץ בשם <filename> • התנאי -d <filename>בודק האםקיימת תיקיה בשם <filename> • ניתן להשתמש בסוגריים עבור קדימויות • ניתן להשתמש בפעולות חשבוניות עלערכים מספריים כמו +, -, * ו-/ • ניתן להשתמש באופרטורים לוגייםלהרכבת תנאים ||, && ו-! > set str1=Hello > if ($str1 == Hello) echo yes yes > if (7 < 20) echo yes yes > if (0 == 00) echo yes > if (0 <= 00) echo yes yes >if (-f a.txt) echo file exists > cat > a.txt Hello world! > if (-f a.txt) echo file exists yes > mkdirmtm > if ( !(-f b.txt && -d mtm) ) echo yes yes מבוא לתכנות מערכות - 234122

  37. התאמת מחרוזות • האופרטור ~= מאפשר התאמת מחרוזת לתבנית • הארגומנט השמאלי הוא מחרוזת רגילה • הארגומנט הימני הוא תבנית אשר יכולה לכלול את הסימנים *, ? ו-[ ] כמו שתואר עבור תבניות של שמות קבצים • האופרטור ~! הוא השלילה של ~= > if (ends_with_z =~ *[zZ]) echo match match > if ("no point in string" !~ *.*) echo no point no point > if ("point - . - in string" !~ *.*) echo no point > set file = test4.in > if ($file =~ test*.in) echo test file test file מבוא לתכנות מערכות - 234122

  38. switch • ניתן ליצור מבנה switchב-C-Shell: switch (<string>) case <pattern1>: <cshell commands> [breaksw] ... case <pattern_n>: <cshell commands> [breaksw] [default: <cshell commands>]endsw • הכללים ב-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 מבוא לתכנות מערכות - 234122

  39. goto • ניתן להשתמש במשפטי goto כמו ב-C goto <label> ... <label>: ... • שימוש במשפטי goto הוא תכנות רע (ללא קשר לשפת התכנות) ולא נהוג להשתמש בהם • השימוש ב-goto יוצר קוד "ספגטי" קשה להבנה מבוא לתכנות מערכות - 234122

  40. העברת פרמטרים בשורת הפקודה • כמו ב-C ניתן לגשת לפרמטרים המועברים בשורת הפקודה לתסריט • המשתנה argvמכיל את רשימת הפרמטרים לתסריט • argv[1] הוא הפרמטר הראשון (ולא שם התסריט) • דרך נוחה יותר לגשת לפרמטר ה-nהיא על ידי $n • $* תוחלף ברשימת כל הפרמטריםלתסריט • $0 תוחלף בשם התסריט echo_script #!/bin/tcsh -f echo command: $0 set number = 1 foreachparam ( $* ) echo parameter $number : $param @ number++ end > echo_scriptaaabbb ccc command: echo_script parameter 1 : aaa parameter 2 : bbb parameter 3 : ccc איך ניתן לדעת את מספר הפרמטרים שהתקבלו? מבוא לתכנות מערכות - 234122

  41. קריאת קלט • ניתן לקרוא שורה מהקלט הסטנדרטי על ידי $< • הביטוי $<יוחלףעל ידי C-Shell בשורת קלט שתיקלט מהקלט הסטנדרטי • בד"כ נשתמש בסוגריים כדי לשמור את כל שורת הקלט • ניתן גם להשתמש במרכאות כדי לשמור עלהרווחים בשורה, כלומר "$<" > set input=$< Hello > echo $input Hello < set line=$< Hello world > echo $line Hello <set line=($<) Hello world > echo $line Hello world מבוא לתכנות מערכות - 234122

  42. עבודה עם קבצים • לא ניתן ב-C-Shellלכתוב ולקרוא מקבצים בצורה ישירה כמו ב-C • כדי לאפשר עבודה עם קבצים נשתמש בהפניות קלט/פלט ותסריטי עזר > cat > file.txt The dingo ate your baby > main_script The first line is: The dingo ate your baby main_script auxiliary_script #!/bin/tcsh -f cat file.txt | auxiliary_script #!/bin/tcsh -f set line=($<) echo "The first line is:" echo "$line" מבוא לתכנות מערכות - 234122

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

  44. העברת והחזרת ערכים • החזרת ערכים מתסריטי העזר יכולה להתבצע בעזרת • שימוש ב-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

  45. דוגמה • כתבו תסריט בשם 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

  46. פתרון • לא ניתן לקרוא את הקבצים ישירות, לכן נחלק את הפתרון לשני תסריטים: • התסריט הראשי search יפעיל את התסריט המשני על כל קובץ • התסריט הנוסף search_in_file יקבל את תוכן הקובץ בקלט הסטנדרטי וידפיס את השורות המתאימות search search_in_file #!/bin/tcsh-f foreachf ($argv[2-]) if (-f $f) then cat $f | search_in_file"$1"$f endif if (-d $f) then search "$1" $f/* endif end #!/bin/tcsh -f setline = "$<" setn=1 while("$line" != "") if("$line" =~ *"$1"*) then echo ${2}:${n}: "$line" endif @ n++ setline = "$<" end מבוא לתכנות מערכות - 234122

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

  48. פתרון • לא נוכל לקרוא את הקובץfootball.txt ישירות מתוך playerולכן ניעזר בתסריט עזר • נשתמש בתסריט search שכתבנומקודם כדי לקבל רק את השורותהרלוונטיות • ניצור את התסריט calc_total אשר יקבלאת השורות הרלוונטיות לשחקן וידפיסאת השורות וסכום השערים calc_total #!/bin/tcsh -f setline = ($<) setsum = 0 while($#line!= 0) @ sum = $sum + $line[4] echo $line[2-] setline = ($<) end echo"total number of goals: $sum" התבנית הכללית של עיבוד קלט התבנית הכללית של עיבוד קלט התבנית הכללית של עיבוד קלט player #!/bin/tcsh -f search "$1"football.txt | calc_total מבוא לתכנות מערכות - 234122

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

  50. פתרון best_player calc_score print_best max #!/bin/tcsh -f setline = ($<) while ($#line> 0) if ($line[3] == $1) then echo $line endif setline = ($<) end #!/bin/tcsh -f setmax = 0 setline= ($<) while ($#line > 0) if($line[3] > $max) then setmax = $line[3] endif setline = ($<) end echo $max #!/bin/tcsh -f @ i = 1 while ( $i <= $#argv ) search "$argv[$i]" football.txt | calc_score >>! temp @ i++ end cat temp | print_best`cat temp | max` if (-f temp) rm -f temp #!/bin/tcsh -f setline = ($<) setsum = 0 setplayer_name = ($line[2-3]) while($#line!= 0) @ sum+= $line[4] setline = ($<) end echo$player_name$sum מבוא לתכנות מערכות - 234122

More Related