59
ססססס סס'6 בבבבבב בבבבבבבבב בUNIX בבבבב בבבבבב בבבבבבבPipeline - בבבבב בbash

תרגול מס' 6

  • Upload
    caraf

  • View
    54

  • Download
    0

Embed Size (px)

DESCRIPTION

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

Citation preview

Page 1: תרגול מס' 6

6תרגול מס' תכניות סטנדרטיות בUNIX שרשור פקודות באמצעותPipeline-עבודה בbash

Page 2: תרגול מס' 6

2מבוא לתכנות מערכות - 234122

Pipelineהרכבת פקודותPipeline

Page 3: תרגול מס' 6

3מבוא לתכנות מערכות - 234122

הרכבת פקודות נניח שברצוננו להדפיס

את התוכן של תיקיה המכילה הרבה קבצים

לא נוכל במצב זה לראות את כל הקבצים

נוכל להשתמש בהפנית לקובץ זמניls פלט הפקודה

:more ולאחר מכן שימוש ב-> ls -l > tmp> more < tmp> rm tmp

Page 4: תרגול מס' 6

4מבוא לתכנות מערכות - 234122

Pipeline-כדי לחסוך את הבלגן שבטיפול בקבצים זמניים ניתן להשתמש בpipeline

המחבר את הפלט של פקודה אחת לקלט של פקודה שניה ישירות כדי לחבר שתי פקודות כך נרשום אותן אחת אחרי השניה כאשר ביניהן

מפריד התו ‘|’:על מנת לראות בשלבים את התוכן של תיקיה גדולה נוכל לרשום כעת

> ls -l | more:ניתן לשלב מספר תכניות בבת אחת

> command1| command2| command3

command1 stdout command2stdin stdout command3stdin

Page 5: תרגול מס' 6

5מבוא לתכנות מערכות - 234122

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

תכנית ב' בעזרתpipeline נוכל להרכיב פקודות מורכבות בעבודה בטרמינל

מתכניות פשוטות

Page 6: תרגול מס' 6

6מבוא לתכנות מערכות - 234122

Bashעבודה ב- מהוbash? תכונות מתקדמות שלbash-עבודת הbash

Page 7: תרגול מס' 6

7מבוא לתכנות מערכות - 234122

ShellShellקליפה( הוא כינוי לתוכנה המקשרת בין המשתמש לבין גרעין מערכת ההפעלה(

טקסטואליshellבדרך כלל המונח בשימוש עבור – מתבצעת על ידי קבלת פקודה מהמשתמש, ביצוע החלפות טקסט בפקודה בהתאם Shellעבודת ה-–

ולבסוף שליחת הפקודה המעובדת למערכת ההפעלהShellלתכונות ה-

-דוגמאות לshell:–Bash )ברירת המחדל ברוב הפצות הלינוקס(–C-Shell ( ברירת המחדל עבור מחשב הstud)–Powershell (shell מתקדם עבור windows)

בקורס זה נלמד אתBash -מלבד מנשק בסיסי לביצוע פקודות הShell בעזרת תכונות מקל עלינו את העבודה

Tabמתקדמות, לדוגמה ההשלמה האוטומטית המתבצעת ע"י לחיצה על -הShell למספר קבצים בנוחות על פקודות, להתייחס לחזור, קיצורים יאפשר לנו להגדיר

אשר נוכל להשתמש בהם בפקודותמשתניםולהגדיר

Page 8: תרגול מס' 6

8מבוא לתכנות מערכות - 234122

Shellהחלפת ה--ניתן להשתמש בפקודה הבאה כדי לקבל את שם הShell-הנוכחי ב Unix

> echo $0tcsh

במחשבים בהםBash אינה Shell-כמו בשרת ה( ברירת המחדל stud ,)לדוגמה כדי לשנות את ברירת המחדל: chsh (change shell)ניתןלהשתמש בפקודה

-חשוב להקפיד לכתוב את שם הShellהייחוס אליו( נכון, אחרת החשבון נהרס( -מלבד החלפת הShell המשמש כברירת מחדל, ניתן תמיד להריץ Shell אחר

כמו כל פקודה אחרת

> chshChanging shell for mtm.old shell: /bin/tcshNew shell: /bin/bashShell will be changed for mtm in approximately 5 minutes>

Page 9: תרגול מס' 6

9מבוא לתכנות מערכות - 234122

echoהפקודה במקרים רבים נרצה להדפיס לפלט מחרוזת, לשם כך ניתן להשתמש

echoבפקודה הפקודהecho מדפיסה את הפרמטרים שקיבלה

> echo [-n] [words]–-nמדפיס ללא ירידת שורה :

> echo Hello world!Hello world!

>

> echo –n Hello world!Hello world!>

Page 10: תרגול מס' 6

10מבוא לתכנות מערכות - 234122

aliasנתינת כינויים לפקודות - הפקודהalias-מאפשרת להגדיר קיצורים ב Shell

> alias <new name>="<command + parameters>"אסור לשים רווחים בסמוך לתו '='–

< לאחר הרצת הפקודה נוכל לרשום את הפקודהnew name כקיצור לפקודה ><command.עם הפרמטרים שהוספנו > ואם כן יבצע החלפה alias יבדוק בשלב עיבור הפקודה האם המילה הראשונה היא Shellה-–

מתאימה כדי לבטלalias ניתן להשתמש בפקודה unalias <alias>

< alias ll="ls –l"> ll-rw-r--r-- 1 user staff 0 Nov 13 15:14 a.c> alias cdex2="cd ~/mtm/ex2"> cdex2> alias GCC="gcc -std=c99 -Wall -Werror -pednatic-errors"> GCC hello.c -o hello> unalias GCC> GCC hello.c -o hello-bash:GCC: Command not found.

Page 11: תרגול מס' 6

11מבוא לתכנות מערכות - 234122

Filename Expansion ניתן לרשום בפקודה תבנית המתייחסת למספר קבצים. במקרה זהbash

יחליף את מחרוזת התבנית בפקודה ברשימת הקבצים המתאימים לתבנית)הסימן * מתאים למחרוזת כלשהי )כולל ריקההסימן ? מתאים לתו כלשהו יחיד] [-ניתן להתייחס למספר תווים אפשריים על ידי שימוש ב

ניתן לרשום את התווים האפשריים אחד אחרי השני במפורש–a-zניתן לרשום טווח של תווים, למשל –

ניתן להתייחס למספר מחרוזות שונות בעזרת } {

אפשרות זו אינה מתחשבת– בקבצים קיימים

< lsaxb.c a3b.c cab.txt a4b.txt> echo files: *files: axb.c a3b.c cab.txt a4b.txt> echo The source files are *.cThe source files are axb.c a3b.c> echo a[0-9]b.*a3b.c a4b.txt> echo a3b.{c,txt}a3b.c a3b.txt

Page 12: תרגול מס' 6

12מבוא לתכנות מערכות - 234122

משתנים-ניתן להציב ערך למשתנה בbashעל ידי השמה ישירה

> <varname>=<value>, לאחר ביצוע השמה למשתנה הוא bashעל משתנים ב- אין צורך להכריז –

מוגדר אוטומטיתערך של משתנה על ידי השמה נוספת להחליףניתן –אסור לשים רווח בין סימן ההשמה לשם המשתנה והערך–

ינסה להריץ פקודה ששמה כשם המשתנהShellאם יהיה כזה רווח ה-•

למשל:$ניתן לקרוא משתנים על ידי שימוש באופרטור ,> echo $<varname>

השימוש במשתנה הוא פשוט החלפת הקריאה למשתנה בערך השמור בו–

Page 13: תרגול מס' 6

13מבוא לתכנות מערכות - 234122

משתנים ניתן לבטל הגדרה של משתנה על ידי הפקודהunset <varname>

< unset my_variableבדרך כלל אין צורך בכך–אם מנסים לקרוא משתנה שאינו מוגדר אז לא מודפס כלום–

$ ניתן להשתמש ב-} { כדי לסמן מהו שם המשתנה לאופרטורמועיל כאשר השימוש במשתנה צמוד למחרוזת נוספת–

> a=Hell> echo $ao

> echo ${a}oHello

Page 14: תרגול מס' 6

14מבוא לתכנות מערכות - 234122

משתנים - מערכים של מחרוזות על ידי שימוש בסוגרייםמערךניתן לשמור במשתנה יחיד

> arr=(1 2 3) ( מהרשימה0קריאת משתנה שקולה לקריאת האיבר הראשון )אינדקס

> echo $arr1

:קריאת כל המערך ניתנת מתבצעת על ידי שימוש ב-]*[ ובסוגריים מסולסלים> echo ${arr[*]{1 2 3> echo $arr[*]1[*]

ניתן לגשת לאיבר יחיד בעזרת אופרטור] [ניתן להוסיף איברים חדשים למערך בשיטה זו–

> arr[3] = 4> echo ${arr[*]{1 2 3 4

Page 15: תרגול מס' 6

15מבוא לתכנות מערכות - 234122

משתנים - מערכים ניתן לקבל את מספר האיברים במערך בעזרת<#{varname$}]*[>:

> echo ${#arr[*]}4

ניתן לגשת לתחומים של איברים במערך במערך> echo A:${arr[*]:0:2} A:1 2> echo B:${arr[*]:1} B:2 3 4> echo C:${arr[*]:2:1} C:3

המספר הראשון מציין את אינדקס ההתחלה של התחום–המספר השני מציין את מספר האיסרים בתחום–

אם הוא אינו מופיע יודפסו כל האיברים החל מהאינדקס המבוקש•

Page 16: תרגול מס' 6

16מבוא לתכנות מערכות - 234122

משתנים - מחרוזות בגרשיים כפוליםניתן לשמור מחרוזות המכילות רווחים בעזרת שימוש

> list=(Matam "Hello world" 17)> echo ${#list[*]} : ${list[*]}3 : Matam Hello world 17> echo ${list[1]}Hello world

קריאת משתנה שערכו מכיל רווחים תגרום לאיבוד הרווחים המדויקים שהיו בין המיליםקודם לכן

> str=" Very crazy spaces "> echo $strVery crazy spaces

Page 17: תרגול מס' 6

17מבוא לתכנות מערכות - 234122

משתנים - מחרוזותניתן להשתמש בגרשיים כפולים כדי לשמור על הרווחים בזמן ההחלפה

> echo "$str" Very crazy spaces

ניתן לקבל את מספר התווים במשתנה ע"י שימוש ב-#, בדומהלקבלת אורכו של מערך

> echo ${#str}29

Page 18: תרגול מס' 6

18מבוא לתכנות מערכות - 234122

משתנים - מערכיםניתן להתייחס למשתנה רגיל כאל רשימה בעלת איבר יחיד

> a=Hello> echo ${a[0]}Hello> str="Hello world"> echo ${str[1]}

> list=(Hello world)> echo ${list[1]}world

בעזרתunsetנוכל לבטל את הרשימה או איבר אחד מתוך הרשימה > unset list[1]> echo ${list[*]}Hello

Page 19: תרגול מס' 6

19מבוא לתכנות מערכות - 234122

משתנים - חישוב ביטויים בניגוד לשפתC ,-למשתנים בbashכל המשתנים הם מסוג מערך של אין טיפוס .

מחרוזות

ניתן להחליף ביטוי אריתמטי בערכו על ידי<(($expression))>הערך המספרי של המחרוזות ישמש בחישוב הביטוי–משתנים יוחלפו בערכם )גם ללא $(– בחישוב0אם אחד הארגומנטים אינו מספר, ערכו יהיה –echo $((3 + 4)) <0משתנה שאינו מוגדר, או ערכו אינו מספר יחושב כ-–

7> n=$((3 * 7 + 4))> echo $n25> a=5> b=7> sum=$(($a + $b))> echo $sum12

> echo $(( Hello ))0> a=4> echo $(( 2 + a ))6> str="Hello world!"> num=17> echo $(( $str * $num ))0

Page 20: תרגול מס' 6

20מבוא לתכנות מערכות - 234122

משתנים - פעולות חשבוניות ניתן לבצע את פעולות חשבוניות שונות בדומה לשפתC:

/ ו-*, -, +פעולות חשבוניות פשוטות: –=השמות: – ++ ו---, =-, =+הגדלות והקטנות: –

רק על מספרים שלמיםניתן לבצע פעולות חשבוניות ניתן להשתמש גם בפקודהlet כדי לבצע פעולה חשבונית

נוח כאשר רוצים להשתמש ב-++ ואין צורך בערך ההחזרה–

> let n=3+4> let n++> echo $n8> $((n++))-bash: 9: command not found

Bash מנסה לבצע " ונכשל9פקודה בשם "

Page 21: תרגול מס' 6

21מבוא לתכנות מערכות - 234122

היסטוריהBash שומר את הפקודות האחרונות

שהתבצעו ומאפשר ביצוען מחדש הדרך הכי פשוטה לגשת להיסטוריה היא על ידי

↓ ו-↑ שימוש ב- ניתן לראות את הפקודות האחרונות שבוצעו

history על ידי הפקודה ניתן לבצע את האחרונה על ידי!! ניתן לבצע את פקודה מספר על ידי!ניתן לבצע את הפקודה האחרונה שהתחילה

<string!>< על ידי stringב->ניתן לבצע את הפקודה האחרונה שמכילה

<string על ידי ><?!string> אפשר להחליףstr1 במחרוזתstr2 בפקודה

.^ str1^str2^ האחרונה ע"י

> history 1 17:20 let a = 3 2 17:21 let b = 4 3 17:22 @ n = $b + $a 4 17:24 echo $n 5 17:28 history> !4echo $n7> !!echo $n7> !letlet b = 4> ls /it/is/avery/long/path

> ^ls^cat^cat /it/is/avery/long/path

החלפות המתבצעות בגלל גישה להיסטוריה מודפסות בזמן ביצוען ולפני ביצוע

הפקודה

Page 22: תרגול מס' 6

22מבוא לתכנות מערכות - 234122

Command Substitution

ניתן "לשרשר" פקודות על ידי שימוש בגרשיים הפוכים`backquotes או backticksבאנגלית: –

Bashיבצע תחילה את הפקודה בתוך ` ` ויחליף אותה בפלט שלה

> echo The length of $str is `echo -n $str | wc -c`The length of Hello is 5> grep –c cow `cat farms_list.txt`farm1:3farm2:2> set a ="there are `ls | wc -l` files in `pwd` "> echo $athere are 662 files in /usr/bin

farm1farm2

farms_list.txt

Page 23: תרגול מס' 6

23מבוא לתכנות מערכות - 234122

סוגי גרשייםמשמשים לשמירה על רווחים" ", גרשיים כפולים ,

משתמשים ב-" " כאשר יש צורך לשמור מחרוזות שלמות במדויק–> sentence="The dingo ate your baby"

בתוך גרשיים אלו לא מתבצעות החלפות של תבניות בשמות הקבצים המתאימים–> echo "*.c" : *.c*.c : main.c app.c hello.c

' ' מונעים את כל ההחלפות בתחומםגרשיים בודדים ,> echo lets make some '$$'lets make some $$

( גרשיים הפוכיםbackticks ) מבצעיםcommand substitution

Page 24: תרגול מס' 6

24מבוא לתכנות מערכות - 234122

shellעבודת ה--עבודת הShell:מתבצעת בלולאה

promptהצגת –המתנה לפקודה–עיבוד הפקודה עד לקבלת פקודה פשוטה–ביצוע הפקודה–

לשם כךBashמשתנים, ההיסטוריה מנהל מבני נתונים פנימיים אשר שומרים את ה שהוגדרו aliasesוה-

הטיפול בפקודה מתבצע בשלושה שלבים עיקריים: הפקודה מופרדת למילים על פי רווחים וטאבים. התווים |,> ו-< ניתוח הפקודה1.

מפרידים בין פקודות: ביצוע החלפות מחרוזות הפקודה עד לקבלת פקודה פשוטהעיבוד הפקודה2.: שליחת הפקודה הפשוטה שהתקבלה לביצוע על ידי מערכת ההפעלהביצוע הפקודה3.

Page 25: תרגול מס' 6

25מבוא לתכנות מערכות - 234122

עיבוד הפקודה בשלב זה מבצעbash החלפות במחרוזת הפקודה עד לקבלת פקודה

פשוטה:

אם הפקודה מכילה שימוש בפקודות קודמות )ע"י שימוש בסימן !( 1.ומודפסת שורת הפקודה שנבחרה החלפה מההיסטוריה מתבצעת

מההיסטוריה aliasמתבצעת החלפה לפי ה- aliasאם המילה הראשונה בפקודה הינה 2.

המוגדר המתאימיםמשתניםהחלפת ביטויים המתחילים ב-$ בערכי ה3.ברשימת הקבצים המתאימהתבניות של שמות קבצים החלפת 4.בתוצאת הפקודהגרשיים הפוכים החלפת פקודות המופיעות בתוך 5.

Page 26: תרגול מס' 6

26מבוא לתכנות מערכות - 234122

ביצוע הפקודה לאחר שהתקבלה פקודה סופית עלbash ,להפעיל את הפקודה המתאימה

הפקודות מתחלקות שני סוגים:,...cd, let, unset, למשל Shellשל ה-פקודות פנימיות –...ls, gcc, cat, sort- שמות קבצי הרצה, למשל פקודות חיצוניות –

אם שם הפקודה מתאים לפקודה פנימית היא תיבחר-אחרת הShellמשתנה יחפש בכל התיקיות המופיעות בpath קובץ הרצה בשם

המתאים,-אם נרצה לאפשר לShellלהריץ תכניות

מהתיקיה הנוכחית ללא שימוש ב-‘.’.PATHניתן להוסיף את התיקיה הנוכחית ל-

. ":" התיקיות מופרדות ע"י סימן ניתן להשתמש בפקודה which כדי לגלות

איזו תכנית תופעל עבור שם פקודה מסוים

> PATH=${PATH[*]}:.> helloHello world!> which hello./hello> which gcc/usr/bin/gcc< which cdWhich: no cd in (…content of PATH…)

Page 27: תרגול מס' 6

27מבוא לתכנות מערכות - 234122

- סיכוםBashעבודה ב--לBash מגוון תוכנות מתקדמות המאפשרות למשתמש מתקדם לבצע

פעולות מסובכות בקלותניתן להתייחס למספר קבצים בבת אחת על ידי שימוש בתבניות ניתן להגדיר כינויים לפקודות ופרמטרים שכיחים בעזרתaliasניתן לקרוא לפקודות שהתבצעו בעבר הקרוב בעזרת ההיסטוריה-ניתן לשמור ערכים במשתנים ולנצלם לפקודות בBash-כל המשתנים בbashהם מסוג רשימות של מחרוזות ניתן להשתמש ב-` ` כדי לבצע החלפת פקודה בפלט שלה בשורות

bashפקודה ב- כל התכונות שלbash מבוצעות על ידי החלפת מחרוזות פשוטה בשלב

עיבוד הפקודה

Page 28: תרגול מס' 6

28מבוא לתכנות מערכות - 234122

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

Page 29: תרגול מס' 6

29מבוא לתכנות מערכות - 234122

אוטומטיזציה נניח )מקרה היפותטי לחלוטין( שברשותנו קבצי בדיקה ופלט לתכנית שלנו

וברצוננו לבדוק את נכונות התכנית מול קבצים אלו

פקודות לכל בדיקה3צריך לכתוב

גם עם שימוש במנגנון ההיסטוריה הרצת הבדיקותמעיקה ולוקחת הרבה זמן מיותר

:תסריט של הרצת הפקודות. ניצור קובץ אשר יכיל "אוטומטיזציההפתרון "לפיו יורצו כל הפקודות לפי הסדר

> mtm_rentals < test1.in > tmpout 2> tmperr> diff expout1 tmpout> diff experr1 tmperr

Page 30: תרגול מס' 6

30מבוא לתכנות מערכות - 234122

sourceהרצת תסריט בעזרת ניתן להריץ קובץ המכיל פקודותBash להלן( - תסריטscript על ידי )

sourceהפקודה -הפקודות יבוצעו בShell כאילו נכתבו בשורת הפקודה אחת אחרי הנוכחי

השניהecho Running test 1mtm_rentals < test1.in > tmpout 2> tmperrdiff expout1 tmpoutdiff experr1 tmperrecho Running test 2mtm_rentals < test2.in > tmpout 2> tmperrdiff expout2 tmpoutdiff experr2 tmperrecho Running test 3mtm_rentals < test3.in > tmpout 2> tmperrdiff expout3 tmpoutdiff experr3 tmperr

run_tests> source run_testsRunning test 1Running test 2Running test 3

Page 31: תרגול מס' 6

31מבוא לתכנות מערכות - 234122

תסריטי אתחול בהתחברות של משתמש למערכת מורץ התסריט.login אשר בתיקית

הבית של המשתמש בפתיחתShell חדש של Bash מורץ התסריט .bashrc הרצות תסריטי האתחול מתבצעות באמצעותsource ולכן הן משפיעות ,

Shellעל מצב ה-

PATH=$PATH:.alias ll="ls -l"alias cdex2="cd ~mtm/public/1011a/ex2"alias GCC="gcc -std=c99 -Wall \

-pedantic-errors -Werror"

.bashrc# welcome messageecho ------ 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 inecho Today is `date`

.login

Page 32: תרגול מס' 6

32מבוא לתכנות מערכות - 234122

הרצת תסריט כקובץ הרצה:ניתן להריץ תסריט כפקודה

התסריט יש להוסיף את השורהבתחילת–#!/bin/bash

שהשורה הראשונה בקובץ מגדירה את התכנית לביצוע Unix מסמן ל-#!•שאר הפקודות בקובץ

•/bin/bash הוא שם התכנית לביצוע הפקודות, במקרה שלנוBash בנוסף יש להוסיף הרשאת ריצה לקובץ–כעת ניתן להריץ את התסריט כמו תכנית רגילה–

בניגוד להרצה באמצעות פקודתsourceתהליך התסריט יבוצע בShell אשר יסתיים בסוף ריצת התסריטחדש

Page 33: תרגול מס' 6

33מבוא לתכנות מערכות - 234122

הרצת תסריט כקובץ הרצה:נמיר את תסריט הרצת הבדיקות שלנו לקובץ הרצה

מתחיל: התסריטבעיה חדשה להסתבך, הוספת בדיקות נוספות

משכפלת קוד בתסריט ולא נוחה )ייתכנו אלפי בדיקות(נשתמש במבני בקרה )תנאים ולולאות( בדומה לשפת פתרון :C

#!/bin/bashecho Running test 1mtm_rentals < test1.in > tmpout 2> tmperrdiff expout1 tmpoutdiff experr1 tmperrecho Running test 2mtm_rentals < test2.in > tmpout 2> tmperrdiff expout2 tmpoutdiff experr2 tmperrecho Running test 3mtm_rentals < test3.in > tmpout 2> tmperrdiff expout3 tmpoutdiff experr3 tmperr

run_tests> chmod a+x run_tests> ./run_testsRunning test 1Running test 2Running test 3

Page 34: תרגול מס' 6

34מבוא לתכנות מערכות - 234122

מבני בקרהBash למשל במבני בקרה מאפשרת שימוש(while -וif בתסריטים )

ובשורת הפקודה

בדומה למבני הבקרה שבשפת בתנאיםמבני הבקרה משתמשים Cהשוואת ערכי מספרים–השוואת מחרוזות–ועוד...–

נעבור על מספר מבני בקרהותנאים שימושיים

> for ((i = 1; $i < 10; i++ )); do> if (($i % 3 == 0)); then> echo 3 divides $i> fi> done3 divides 33 divides 63 divides 9

Page 35: תרגול מס' 6

35מבוא לתכנות מערכות - 234122

while ניתן ליצור לולאותwhile -בbash:

while <expression>; do<command1><command2>...

done< ממשיך להתקייםexpressionהפקודות בגוף הלולאה יבוצעו כל עוד >– מהטרמינלישירות כמו שאר מבני הבקרה ניתנות לביצוע whileלולאות –

#!/bin/bashi=1while (( 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

> ./run_testsRunning test 1Running test 2Running test 3

> i=1> while (( i <= 3)); do> echo $i> let i++> done123

Page 36: תרגול מס' 6

36מבוא לתכנות מערכות - 234122

for-שימוש נוסף בfor:הוא מעבר על על איברי המערך

for <varname> in <array> ; do<command1><command2>...

done<varnameהוא שם המשתנה שיכיל בכל פעם איבר מהרשימה ><arrayהיא רשימה של מחרוזות >העדיפו להשתמש בשיטה זו על פני שימוש מפורש באינדקסים

Page 37: תרגול מס' 6

37מבוא לתכנות מערכות - 234122

for לולאתfor משמשת בדומה לשפת Cלמעבר נוח יותר על תחום מספרים

#!/bin/bashfor ((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 tmperrdone

run_tests

> ./run_testsRunning test1.inRunning test2.inRunning test3.in

Page 38: תרגול מס' 6

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

Page 39: תרגול מס' 6

39מבוא לתכנות מערכות - 234122

while ו-if אפשריים ב-ביטוייםקיימות מספר אפשרויות לכתיבת התנאים בלולאות ומשפטי תנאי:]] [[ ניתן לרשום תנאים בתוך

האופרטורים ==, < ו-> משווים מחרוזות )לפי סדר לקסיקוגרפי(–eq, -gt, -le-ניתן לבצע השוואת על ערכי מספרים בעזרת דגלים כגון –חשוב להקפיד על תו הרווח בין הסוגריים לתוכן התנאי כדי למנוע שגיאות –

bash> str1=Helloב-> if [[ $str1 == Hello ]]; then echo true; fitrue> if [[ hello == Hello ]]; then echo true; fi> if [[ 11 < 7 ]]; then echo true; fitrue> if [[ 11 -le 7 ]]; then echo true; fi

> if [[ 11 -eq 11 ]]; then echo true; fitrue> if [[ 0 -eq Hello ]]; then echo true; fitrue

זו אינה השוואת ערכים מספריים

עבור ערך שאינו מייצג 0מספר משתמשים ב-

לחישוב

Page 40: תרגול מס' 6

40מבוא לתכנות מערכות - 234122

while ו-if אפשריים ב-ביטויים:בתוך ]] [[ ניתן להשתמש בתנאים מועילים נוספים, למשל

<filename>< בודק האם קיים קובץ בשם f <filename-התנאי –<dirname< בודק האם קיימת תיקייה בשם >d <dirnameהתנאי -–

:ניתן לבדוק תנאים מורכבים יותרCניתן להשתמש באופרטורים &&, ||, ו-! כמו בשפת –

הקפידו להשאיר רווח אחרי ! כדי להימנע משגיאות בגלל מנגנון ההיסטוריה•ניתן להשתמש בסוגריים כדי לקבוע את הקדימויות–

> if [[ -f a.txt ]]; then echo file exists; fi> cat > a.txtHello world!> if [[ -f a.txt ]]; then echo file exists; fifile exists> mkdir mtm> if [[ ! (-f b.txt && -d mtm) ]]; then echo yes; fiyes

Page 41: תרגול מס' 6

41מבוא לתכנות מערכות - 234122

התאמת מחרוזות מאפשר התאמת מחרוזת =בתוך תנאי מהצורה ]] [[, האופרטור

לתבניתהארגומנט השמאלי הוא מחרוזת רגילה–כמו ] [ ו-?, *אשר יכולה לכלול את הסימנים תבנית הארגומנט הימני הוא –

שתואר עבור תבניות של שמות קבצים= האופרטור =! הוא השלילה של אופרטור ההתאמה

"end_with_z="some string with z <שימו לב שהמשמעות של = ו-== שונה–> if [[ "$end_with_z" = *[zZ] ]]; then echo match; fimatch> if [[ "this string start with t" = t* ]]; then echo true; fitrue> if [[ "this string doesn't start with t" = [^t]* ]]; then echo true; fi> file=test4.in> if [[ $file = test*.in ]]; then echo test file; fitest file> if [[ "string doesn't start with t" != t* ]]; then echo true; fitrue

Page 42: תרגול מס' 6

42מבוא לתכנות מערכות - 234122

while ו-if אפשריים ב-ביטויים(( ניתן להגדיר תנאי בתוך))

בתוך )) (( האופרטורים ==, =!, < ו- > מתייחסים לערכים מספריים–אין צורך לרשום $ לפני שם משתנה–ניתן לבצע פעולות חשבוניות–

$)) (( מתנהגים כמו ביצוע פעולות חשבוניות בעזרת )) (( תנאים המוגדרים בעזרת

> if (( 11 < 7 )); then echo true; fi> i=5> if (( i >= 0 && i <= 10 )); then echo true; fitrue> if [[ 11 -eq 11 ]]; then echo true; fitrue> if (( 0 == Hello )); then echo true; fitrue> if (( ++i == 6 )); then echo true; fitrue> if (( ++i == 6 )); then echo true; fi

Page 43: תרגול מס' 6

43מבוא לתכנות מערכות - 234122

-כמו בCניתן לגשת לפרמטרים המועברים בשורת הפקודה לתסריט -הפרמטר הn לתסריט נקרא פשוט n וניתן לקרוא אותו על ידי ,$n*$יוחלף ברשימת כל הארגומנטים לתסריט

אם ייתכנו רווחים בתוך הארגומנטים ניתן להשתמש ב-"$@" כדי לשמור על –מספר האגומנטים הנכון

$0יוחלף בשם התסריט #$יוחלף במספר הארגומנטים

> echo_script aaa bbb ccccommand: echo_script3 argumentsparameter 1 : aaaparameter 2 : bbbparameter 3 : ccc

העברת פרמטרים בשורת הפקודה

#!/bin/bashecho command: $0echo $# arguments let number=1for param in $*; do echo parameter $((number++)) : $paramdone

echo_script

Page 44: תרגול מס' 6

44מבוא לתכנות מערכות - 234122

פונקציות-ניתן להגדיר בbash:פונקציות בצורה כזו

function <name> { <commands>}

פונקציה חייבת להכיל לפחות פקודה אחת–השימוש בפונקציה יכול להתבצע רק אחרי הגדרתה–אפשר להעביר לפונקציה ארגומנטים–

הפונקציה משתמשת בהם בדומה לשימוש•בארגומנטים המועברים לתסריט

הפונקציה אינה יכולה לגשת לארגומנטים•של התסריט שקרא לה

Page 45: תרגול מס' 6

45מבוא לתכנות מערכות - 234122

פונקציות כדי ליצור משתנה מקומי בפונקציה יש להכריז עליו תחילה עםlocal:

> using_localoriginal_a original_boriginal_a surprise_b

#!/bin/bashfunction surprise { local a=surprise_a b=surprise_b}a=original_ab=original_becho $a $bsurpriseecho $a $b

using_local

Page 46: תרגול מס' 6

46מבוא לתכנות מערכות - 234122

פונקציות ניתן "להחזיר" ערכים מפונקציה בעזרתcommand subsitution

(backticks):

> sum_numbers 1 2 3 4 515

#!/bin/bashfunction sum { local result=0 for num in $*; do let result+=$num done echo $result}n=`sum $*`echo $n

sum_numbers

ביטוי זה יוחלף בסכום הרצוי

Page 47: תרגול מס' 6

47מבוא לתכנות מערכות - 234122

קריאת קלט ניתן לקרוא שורה מהקלט הסטנדרטי על ידיread <flags> <variable

name>השורה תיקלט לתוך שם המשתנה שהוגדר– יחלק את השורה לפי מילים לתוך מערךaהדגל -–

הביטויread על ידי יוחלף bash בשורת קלט שתיקלט מהקלט read line <הסטנדרטי

Hello world> echo $lineHello world> read -a lineHello world> echo $lineHello> echo ${line[*]}Hello world

Page 48: תרגול מס' 6

48מבוא לתכנות מערכות - 234122

עבודה עם קבצים דרך פשוטה לקריאת קובץ היא על ידי שימוש בהפניית קלט ושימוש

:readב-

:דרך פשוטה לקרוא קובץ שורה אחר שורה היא כך#!/bin/bashcounter=0while read line; do echo $line let counter++done < "$1"echo $counter

lines_counter

> cat hello.txtHello world!> read line < hello.txt> echo $lineHello world!

> cat lines.txtfirst linesecond line> lines_counter lines.txt first linesecond line2

Page 49: תרגול מס' 6

49מבוא לתכנות מערכות - 234122

חלוקה פונקציונלית של תסריטים

-שימו לב שניתן להשתמש בbash כדי לערבב תסריטים עם תכניות בקלותבשפות שונות שנכתבו

scripting languagesמכאן מגיע כוחן של שפות תסריטים - –

ניתן להעביר פרמטרים לתסריטי עזרבעזרת פרמטרים בשרות הפקודה–pipelineבעזרת –בעזרת קבצים זמניים–

ניתן לקבל ערכים חזרה מתסריטי עזרבעזרת פלט מתסריט העזר–

Page 50: תרגול מס' 6

50מבוא לתכנות מערכות - 234122

העברת והחזרת ערכים העברת פרמטרים לתסריטי עזר

יכולה להתבצע בדרכים הבאותשורת הפקודהב–

helper_script $arg1 $arg2

pipelineבעזרת –echo $arg1 $arg2 | helper_script

דרך קובץ זמני–echo $arg1 $arg2 > temphelper_script < temp

החזרת ערכים מתסריטי העזריכולה להתבצע בעזרת

backticksשימוש ב-–set result = `helper_script`

pipelineהעברה לתסריט אחר ב-–helper_script | another_script

דרך קובץ זמני–helper_script > temp

Page 51: תרגול מס' 6

51מבוא לתכנות מערכות - 234122

דוגמה כתבו תסריט בשם search אשר מקבל מחרוזת ושמות קבצים ומדפיס את

כל השורות המופיעות בקבצים הללו המכילות את המחרוזת המבוקשתאם מתקבל שם תיקיה, ייבדקו כל הקבצים תחת התיקיה הזו רקורסיבית–

> search Blue scene35.txtscene35.txt : 37 : LAUNCELOT: Blue.scene35.txt : 55 : GALAHAD: Blue. No yel-- Auuuuuuuugh!> search swallow scene*.txtscene1.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 farmsfarms/animals/animals.txt : 8 : cowfarms/farm1.txt : 2 : cow Betsyfarms/farm1.txt : 3 : slim cow Dazyfarms/farm1.txt : 4 : fat cow Burgerfarms/farm1.txt : 5 : two cows Dartsy & Teofarms/farm2.txt : 2 : cow Lenifarms/farm2.txt : 4 : cow Oreo

Page 52: תרגול מס' 6

52מבוא לתכנות מערכות - 234122

פתרון נכתוב תסריט בשםsearch

התסריט ישתמש בפונקצית עזרהקוראת קובץ ומוצאת את השורות

המתאימות בעזרת התאמת מחרוזות

#!/bin/bashfunction 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 "$2" ]]; then search_file "$1" $file fi if [[ -d "$2" ]]; then search "$1" $file/* fidone

search

Page 53: תרגול מס' 6

53מבוא לתכנות מערכות - 234122

דוגמה נוספת נתון קובץ בשםfootball.txt המכיל

נתונים על שערים שהובקעו במשחקי כדורגל

,כל שורה בקובץ מציינת שם של שחקןמספר השערים שהבקיע במשחק

שנערך בתאריך מסוים, שם הקבוצהבה הוא שיחק ושם הקבוצה היריבה

ברצוננו לכתוב תסריט בשםplayer אשר יקבל כפרמטר שם של שחקן

וידפיס את כל השורות עבורו ואת סכוםfootball.txtמהקובץ

מספר השערים שהבקיע

Alon Miz. 2 23/10/93 Macabi-Haifa Macabi-Tel-AvivIzak Zoh. 1 12/11/93 Macabi-Tel-Aviv Hapoel-Beer-ShevaRonen Ha. 3 27/12/93 Hapoel-Tel-Aviv Macabi-Tel-AvivReuven A. 2 12/11/93 Macabi-Haifa Hapoel-Tel-AvivEyal Ber. 1 20/11/93 Macabi-Haifa Macabi-Tel-Aviv Izak Zoh. 1 12/11/93 Macabi-Tel-Aviv Hapoel-HaifaAlon Miz. 2 26/10/93 Macabi-Haifa Beitar-JerusalemIzak Zoh. 2 12/12/93 Macabi-Tel-Aviv Macabi-HiafaAlon Miz. 2 23/12/93 Macabi-Haifa Macabi-Pet-TikvaRonen Ha.3 27/11/93 Hapoel-Tel-Aviv Macabi-Haifa

football.txt

> player "Alon Miz."Alon Miz. 2 23/10/93 Macabi-Haifa Macabi-Tel-AvivAlon Miz. 2 26/10/93 Macabi-Haifa Beitar-JerusalemAlon Miz. 2 23/12/93 Macabi-Haifa Macabi-Pet-TikvaTotal number of goals: 6

Page 54: תרגול מס' 6

54מבוא לתכנות מערכות - 234122

פתרון נשתמש בתסריטsearchשכתבנו

מקודם כדי לקבל רק את השורותהרלוונטיות

נכתוב פונקצית עזר בשםcalc_totalאשר תקרא את השורות מהקלט

הסטנדרטי שלה ותסכום את מספרהגולים של השחקן תוך כדי הדפסתן

#!/bin/bashfunction 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

Page 55: תרגול מס' 6

55מבוא לתכנות מערכות - 234122

דוגמה שלישית כתבו תסריט לדירוג שחקנים בשםbest_player אשר יקבל רשימה של

שמות שחקנים בשורת הפקודה וידפיס את שם השחקן שהבקיע את מרב הגולים

אם קיימים מספר שחקנים שהבקיעו את מרב הגולים יודפסו שמות כל –השחקנים

לכל שחקן יש להדפיס את שמו ומספר הגולים שהבקיע–

> best_player "Alon Miz." "Izak Zoh." "Ronen Ha." "Reuven A."Alon Miz. 6Ronen Ha. 6

Page 56: תרגול מס' 6

פתרון

23412256מבוא לתכנות מערכות -

max_goals=0for player in "$@"; do goals=`sum_player_goals "$player"` if (( goals > max_goals )); then max_goals=$goals fidonefor player in "$@"; do goals=`sum_player_goals "$player"` if (( goals >= max_goals )); then echo "$player" $max_goals fidone

#!/bin/bash# Sums the goals from lines in# the correct formatfunction sum_goals { local sum=0 while read -a line; do let sum+=${line[6]} done echo $sum}

# Sums all the goals of target playerfunction sum_player_goals { ./search "$1" football.txt | sum_goals}

best_player

Page 57: תרגול מס' 6

57מבוא לתכנות מערכות - 234122

C ל-bashהשוואה בין Bash שפת תסריטים היא -scripting language

.Perl, Tcl, Python, Rubyשפות תסריטים נוספות: –

C שפת תכנות מערכת היא -system programming language#.C++, Java, Cשפות מערכת נוספות: –

Page 58: תרגול מס' 6

58מבוא לתכנות מערכות - 234122

C ל-bashהשוואה בין של יתרונות bash על C:

מחרוזות ומשתניםעבודה נוחה עם –(7" תכניות קיימות )עוד על כך בתרגול להדביקנוח "– משמעותית לחלק מהמשימותקצרקוד –על דברים לא צריך להכריז אין קומפיילר -–

של חסרונות bash לעומת C:אין בדיקותאין קומפיילר - –

מאפשר באגים מסוכנים)לעתים פי כמה מאות( איטית–

-נבחר בbash מטלות פשוטות וקצרות שזמן הביצוע שלהן לא קריטי עבור

read deposits account_balance=100for d in ${deposits[*]}; do acount_balance=$((account_balance + d))doneecho $account_balance

Page 59: תרגול מס' 6

59מבוא לתכנות מערכות - 234122

bashסיכום - כדי לחסוך ביצוע חוזר וידני של פעולות ניתן ליצור תסריטים המכילים רצף

או הפיכתם לקובץ הרצהsourceפקודות שימושי ולהריצם בעזרת -בbash קיימים מבני הבקרה while , for ו if המאפשרים כתיבת קוד

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

בפונקציה וכתיבתו לפלט נוח להדביק תסריטים ביחד בעזרתpipeline-ו command substitution כדי

לפתור בקלות בעיות-נשתמש בbash עבור מטלות פשוטות שאינן דורשות חישובים רבים, עבור

Cשאר המטלות נמשיך להשתמש ב-