Κεθάιαην 8 8 Δηζαγσγή ζηα ζελάξηα θειύθνπο 8.1 Κέιπθνο ή Φινηόο (shell) Σν θέιπθνο (shell) είλαη ην πξφγξακκα πνπ δηεξκελεχεη (interpret) ηηο εληνιέο πνπ εηζάγνληαη απφ ην πιεθηξνιφγην. Δθηφο απφ ηελ αλάγλσζε εληνιψλ απφ ην πιεθηξνιφγην, νη εληνιέο είλαη δπλαηφλ λα ηνπνζεηεζνχλ ζε έλα αξρείν θαη λα αλαγλσζηνχλ απφ απηφ. Έλα αξρείν πνπ πεξηέρεη εληνιέο θειχθνπο νλνκάδεηαη ζελάξην θειχθνπο (shell script). Ο φξνο ζελάξην (script) ρξεζηκνπνηείηαη γηα φιεο ηηο γιψζζεο πξνγξακκαηηζκνχ πνπ είλαη δηεξκελεπηέο (interpreters), φπσο γηα παξάδεηγκα: php script, perl script θηι. Σν θέιπθνο ζηελ πξαγκαηηθφηεηα είλαη έλα πξφγξακκα ην νπνίν απφ ηε κηα πιεπξά δηαβάδεη ηηο εληνιέο ηνπ ρξήζηε θαη απφ ηελ άιιε επηθνηλσλεί κε ηνλ ππξήλα ηνπ Λεηηνπξγηθνχ πζηήκαηνο γηα λα «ζηείιεη» ηηο εληνιέο πξνο εθηέιεζε. Χρήστες Κελφφη Εφαρμογές Πυρήνας Υλικό ρήκα 8.1: Ιεξάξρεζε ζηα ηκήκαηα ηνπ Unix. ε θάζε ζχζηεκα UNIX ππάξρνπλ ηνπιάρηζηνλ δχν δηαζέζηκα θειχθε θαη απηά ζπλήζσο είλαη ην Bourne shell (sh) θαη ην C-shell (csh). Χζηφζν, ε γιψζζα θαη ε ζχληαμε πνπ ρξεζηκνπνηείηαη γηα ηελ επηθνηλσλία κε θαζέλα απφ απηά είλαη δηαθνξεηηθή. Όπσο βιέπνπκε ζηε ιίζηα πνπ αθνινπζεί, ππάξρνπλ πνιιά δηαθνξεηηθά θειχθε: Οηθνγέλεηα Bourne Shell: Bourne Shell (sh), Bourne-Again Shell (bash), Korn Shell (ksh), MirBSD Korn Shell (mksh), Almquist shell (ash), Z-sh Οηθνγέλεηα C-shell: C-shell (csh), Tc-shell (tcsh). Καηά ηε ζπγγξαθή ηνπ παξφληνο ην πεξηζζφηεξν δηαδεδνκέλν θέιπθνο είλαη ην Bourne again shell (bash). Σν bash είλαη βειηησλέλε έθδνζε ηνπ sh θαη είλαη πιένλ ν εμ νξηζκνχ θινηφο ζε ζπζηήκαηα linux. Μάιηζηα ζε αξθεηέο πεξηπηψζεηο ε βαζηθή έθδνζε Bourne Shell δελ ππάξρεη θαλ, θαη ε εληνιή sh είλαη ζχλδεζκνο ζηελ εληνιή bash. 175
Αλεμάξηεηα από ην θέιπθνο πνπ ρξεζηκνπνηείηαη, όια ηα θειύθε έρνπλ σο ζηόρν λα παξέρνπλ ζην UNIX κηα δηεπαθή ρξήζηε (user interface). ρεδφλ φια ηα θειχθε έρνπλ ηηο παξαθάησ δπλαηφηεηεο-ηδηφηεηεο: δηεξκελεία (interpretation) θαη επεμεξγαζία ηεο γξακκήο εληνιψλ, ππνζηήξημε δεζκεπκέλσλ ιέμεσλ, ππνζηήξημε ραξαθηήξσλ κπαιαληέξ (wildcards), εθηέιεζε εληνιψλ (πξνγξακκάησλ ή εζσηεξηθψλ εληνιψλ ηνπ θειχθνπο - bultin commands), δηαρείξηζε αξρείσλ: αλαθαηεχζπλζε εηζφδνπ / εμφδνπ θαη δηαζσιελψζεηο, ππνζηήξημε κεηαβιεηψλ, θαζνξηζκφ ςεπδσλχκσλ (aliases), έιεγρν ηνπ πεξηβάιινληνο θαη δεκηνπξγία πεξηβάιινληνο πξνζαξκνζκέλνπ ζηηο απαηηήζεηο ηνπ ρξήζηε, δεκηνπξγία ζελαξίσλ θινηνχ (shell scripts). 8.1.1 Σν πξώην κνπ ζελάξην θειύθνπο Σν θέιπθνο, φπσο θαη ηα θίιηξα, έρνπλ ηε δπλαηφηεηα, αληί λα δηαβάδνπλ δεδνκέλα απφ ηελ θαλνληθή είζνδν, λα κπνξνχλ λα ηα δηαβάδνπλ θαη απφ αξρείν. ηελ πεξίπησζε ηνπ θειχθνπο ηα δεδνκέλα είλαη ζηελ πξαγκαηηθφηεηα εληνιέο. Έηζη, αλ εθηειέζνπκε ηελ εληνιή ηνπ θειχθνπο θαη δψζνπκε σο φξηζκα έλα φλνκα αξρείνπ, ηφηε ην θέιπθνο αληί λα δηαβάδεη εληνιέο απφ ην ηεξκαηηθφ (θαλνληθή είζνδν) ζα ηηο δηαβάδεη απφ ην αξρείν. Φηηάρλνπκε, ινηπφλ, ην αξρείν file1 πνπ πεξηέρεη εληνιέο, φπσο θαίλεηαη παξαθάησ: bash-2.05a$ cat file1 ls -l whoami date bash-2.05a$ sh file1 total 24 -rw-r--r-- 1 asidirop it 314 Jan 11 2003 cc -rw-r--r-- 1 asidirop it 18 Nov 20 15:22 file1 -rw-r--r-- 1 asidirop it 183 Jan 8 2003 list asidirop Mon Nov 20 15:23:05 EET 2006 bash-2.05a$ Δθηειψληαο ηελ εληνιή "sh file1" εθηειείηαη ην sh (ην θέιπθφο καο) κε φξηζκα ην αξρείν file1. Όηαλ ζα δεκηνπξγεζεί ε δηεξγαζία ηνπ sh, ζα αλαγλσξίζεη φηη δφζεθε φξηζκα, νπφηε θαη δελ ζα πεξηκέλεη λα δηαβάζεη εληνιέο απφ ηελ θαλνληθή είζνδν, αιιά ζα αλνίμεη ην αξρείν file1 γηα αλάγλσζε θαη ζα δηαβάδεη απφ εθεί γξακκή-γξακκή. Κάζε γξακκή αληηζηνηρεί ζε κηα εληνιή. πλεπψο, κεηά ηελ αλάγλσζε κηαο γξακκήο, ην θέιπθνο εθηειεί ηελ εληνιή πνπ πεξηέρεηαη ζε απηήλ. Έηζη, είλαη ην ίδην κε ην λα έγξαθε ν ρξήζηεο ηηο εληνιέο ζην ηεξκαηηθφ. Αληί λα δηαβαζηνχλ νη εληνιέο απφ ην ηεξκαηηθφ, δηαβάδνληαη απφ ην αξρείν. 176
Όηαλ έλα αξρείν πεξηέρεη text ην νπνίν είλαη εληνιέο, ηόηε απηό ην αξρείν νλνκάδεηαη ζελάξην (script). Όηαλ ην ζελάξην πεξηέρεη εληνιέο γηα ην θέιπθνο (shell), νλνκάδεηαη ζελάξην θειύθνπο (shell script). Μεηνλέθηεκα ζηνλ παξαπάλσ ηξφπν είλαη φηη πξέπεη λα γλσξίδεη ν ρξήζηεο αλ ην ζελάξην θειχθνπο είλαη γξακκέλν γηα ην θέιπθνο sh, ή γηα ην θέιπθνο bash, ή γηα ην csh θηι. Όπσο αλαθέξακε πξηλ, ηα δηάθνξα θειχθε έρνπλ αζπκβαηφηεηεο κεηαμχ ηνπο. πλεπψο, αλ ν ρξήζηεο πξνζπαζήζεη λα εθηειέζεη έλα ζελάξην πνπ είλαη γξακκέλν γηα csh ρξεζηκνπνηψληαο ην bash, ην πην πηζαλφ είλαη λα ππάξμεη απνηπρία ζηελ εθηέιεζε. Όπσο αλαθέξακε πξηλ, ζην Unix ηα ζελάξηα ρξεζηκνπνηνχληαη ζπρλά (shell scripts, perl scripts, python scripts, awk scripts θ.α.). Δπεηδή, ινηπφλ, δελ είλαη δπλαηφ λα γλσξίδεη ν ρξήζηεο γηα θάζε ζελάξην πνπ πξνζπαζεί λα εθηειέζεη ηε γιψζζα πξνγξακκαηηζκνχ γηα ηελ νπνία είλαη γξακκέλν, ππάξρεη ε εμήο ζχκβαζε: ηελ αξρή ηνπ ζελαξίνπ κπαίλνπλ νη ραξαθηήξεο #! αθνινπζνχκελνη απφ ηελ απφιπηε δηαδξνκή ηνπ αληίζηνηρνπ δηεξκελεπηή. Έηζη, έλα ζελάξην γηα bash ζα πξέπεη λα μεθηλά κε: #!/bin/bash Αληίζηνηρα, έλα ζελάξην γηα perl μεθηλά κε #!/usr/bin/perl, έλα ζελάξην γηα csh μεθηλά κε #!/bin/csh θηι. Ο ππξήλαο ηνπ Unix, φηαλ πξνζπαζεί λα εθηειέζεη έλα πξφγξακκα, αξρηθά ειέγρεη αλ είλαη binary θαη αληηζηνηρεί ζηελ αξρηηεθηνληθή ηνπ ηξέρνληνο επεμεξγαζηή. Δάλ λαη, ηφηε μεθηλά ηε δηεξγαζία θνξηψλνληαο ηνλ δπαδηθφ θψδηθα (binary code) ζηε κλήκε. Δάλ φρη, ηφηε ειέγρεη εάλ είλαη αξρείν θεηκέλνπ (text file). Όια ηα ζελάξηα είλαη αξρεία θεηκέλνπ. Δάλ, ινηπφλ, είλαη αξρείν θεηκέλνπ, ηφηε ειέγρεη ηνπο δπν πξψηνπο ραξαθηήξεο ηνπ αξρείνπ. Δάλ απηνί νη δπν πξψηνη ραξαθηήξεο είλαη νη #! ηφηε αληηιακβάλεηαη φηη πξφθεηηαη γηα ζελάξην, θαη δηαβάδεη ηελ ππφινηπε πξψηε γξακκή γηα λα βξεη ηνλ δηεξκελεπηή πνπ πξέπεη λα εθηειέζεη. Έζησ έλα αξρείν κε φλνκα file1 πνπ πεξηέρεη: #!/path/command Lala Foo Όηαλ πξνζπαζήζνπκε λα «εθηειέζνπκε» ην file1 κε ηελ εληνιή:./file1 ηφηε ην UNIX ζα αλαγλσξίζεη φηη δελ πξφθεηηαη γηα αξρείν κε δπαδηθφ θψδηθα (binary file) αιιά γηα αξρείν θεηκέλνπ (text). Θα δηαβάζεη ηελ πξψηε γξακκή θαη ζα εθηειέζεη ηελ εληνιή: /path/command./file1 177
Άξα, αλ ε πξψηε γξακκή ηνπ αξρείνπ file2 είλαη #!/usr/bin/perl, ηφηε εθηειψληαο ην file2 ν ππξήλαο εθηειεί ηελ εληνιή: /usr/bin/perl./file2 Αλ ε πξψηε γξακκή ηνπ file3 είλαη #!/bin/bash, ηφηε εθηειψληαο ην file3 ν ππξήλαο εθηειεί ηελ εληνιή: /bin/bash./file3 Με ην παξαπάλσ, μεθηλά νπζηαζηηθά κηα λέα δηεξγαζία θειχθνπο κε φξηζκα ην αξρείν file3. πλεπψο, μεθηλά έλα θέιπθνο ην νπνίν ζα δηαβάδεη εληνιέο απφ ην αξρείν file3. 8.1.2 Δθηέιεζε ζελαξίσλ θαη άδεηεο ρξήζεο Γηα λα κπνξεί λα εθηειέζεη θάπνηνο ρξήζηεο έλα πξφγξακκα, ζα πξέπεη λα έρεη άδεηα εθηέιεζεο γηα ην αξρείν πνπ αληηζηνηρεί ζην πξφγξακκα. Σν ίδην ηζρχεη θαη γηα ηα ζελάξηα, ηα νπνία, ζηελ νπζία, είλαη πξνγξάκκαηα. Όηαλ δεκηνπξγνύκε ζελάξηα, πξέπεη λα ηνπο δώζνπκε ηελ άδεηα πξόζβαζεο execute. Η άδεηα execute, όπσο έρνπκε αλαθέξεη ζηελ Παξάγξαθν 5.3.1, δελ ηίζεηαη από κόλε ηεο, όηαλ δεκηνπξγνύληαη αξρεία, αιιά πξέπεη λα δνζεί εθ ησλ πζηέξσλ. Αλ ην αξρείν δελ έρεη άδεηα execute, ζα πάξνπκε ην κήλπκα Permission denied, φπσο θάζε θνξά πνπ γίλεηαη πξνζπάζεηα εθηέιεζεο πξνγξάκκαηνο γηα ην νπνίν δελ ππάξρνπλ ηα θαηάιιεια δηθαηψκαηα: aetos_test_27_$./file1./file1: Permission denied. aetos_test_27_$ ls -l total 24 -rw-r--r-- 1 asidirop it 314 Jan 11 2003 cc -rw------- 1 asidirop it 28 Nov 20 18:40 file1 -rw-r--r-- 1 asidirop it 183 Jan 8 2003 list ε αληίζεζε κε ηα πξνγξάκκαηα ηχπνπ binary, γηα ηα νπνία αξθεί ην δηθαίσκα execute γηα ηελ εθηέιεζή ηνπο ρσξίο λα ρξεηάδεηαη ην δηθαίσκα read, ζηελ πεξίπησζε ησλ ζελαξίσλ ππάξρνπλ επηπιένλ πεξηνξηζκνί. Έζησ, ινηπφλ, ζην πξνεγνχκελν παξάδεηγκα έρνπκε δψζεη ζην file1 ηελ άδεηα execute αιιά φρη ηελ άδεηα read. Όηαλ πξνζπαζήζνπκε λα εθηειέζνπκε ην file1, ζα πάξνπκε ην δηαθνξεηηθφ απφ ηελ πξνεγνχκελε πεξίπησζε κήλπκα cannot open: Permission denied. Απηφ πνπ ζπλέβε είλαη φηη ην file1 πέξαζε ηνλ έιεγρν άδεηαο execute, ν ππξήλαο έιεγμε ηνλ ηχπν ηνπ αξρείνπ θαη δηάβαζε ηελ πξψηε γξακκή θαη κεηά εθηέιεζε ηελ εληνιή "/bin/sh file1". Ζ εληνιή εθηειείηαη θαλνληθά, μεθηλά ην θέιπθνο θαη (ην θέιπθνο) πξνζπαζεί λα αλνίμεη ην αξρείν file1, γηα ηελ αλάγλσζε ησλ εληνιψλ. Δπεηδή, φκσο δελ ππάξρεη ην δηθαίσκα αλάγλσζεο (read), ην θέιπθνο εκθαλίδεη ην κήλπκα ζθάικαηνο. 178
aetos_test_27_$./file1 /bin/sh:./file1: cannot open: Permission denied aetos_test_45_$ /bin/sh file1 /bin/sh: file1: cannot open: Permission denied aetos_test_27_$ ls -l total 24 -rw-r--r-- 1 asidirop it 314 Jan 11 2003 cc --wx------ 1 asidirop it 28 Nov 20 18:48 file1 -rw-r--r-- 1 asidirop it 183 Jan 8 2003 list 8.1.3 Απνζθαικάησζε ζελαξίσλ θειύθνπο Όια ηα θειχθε παξέρνπλ ηελ επηινγή v, γηα λα εκθαλίδεηαη ζηελ νζφλε θάζε γξακκή ηνπ ζελαξίνπ, θαζψο απηφ δηαβάδεηαη θαη ηελ επηινγή x, γηα λα εκθαλίδνληαη νη εληνιέο, θαζψο εθηεινχληαη. Οη επηινγέο απηέο είλαη πνιχ ρξήζηκεο γηα ηε ζπληαθηηθή αλάιπζε ησλ εληνιψλ. Μπνξνχκε λα ελζσκαηψζνπκε απηέο ηηο επηινγέο ζηελ πξψηε γξακκή ηνπ ζελαξίνπ, φπσο θαη θάζε άιιε επηινγή κε ηνλ ίδην ηξφπν. ην παξαθάησ παξάδεηγκα πξνζζέηνπκε ζην ζελάξην file2 ην φξηζκα -v, φπσο θαίλεηαη παξαθάησ. Καηά ηελ εθηέιεζε ηνπ αξρείνπ ν ππξήλαο ζα δηαβάζεη ηελ πξψηε γξακκή θαη απηφ πνπ ζα εθηειέζεη είλαη /bin/sh -v file2. Παξαθάησ βιέπνπκε πνην ζα είλαη ην απνηέιεζκα ρξεζηκνπνηψληαο ην -v. Σν θέιπθνο ζα ηππψλεη θάζε γξακκή ηνπ αξρείνπ πξηλ ηελ εθηειέζεη. Θα ηππψζεη αθφκε θαη ηηο γξακκέο πνπ πεξηέρνπλ ζρφιηα θαη φρη εληνιέο. bash-2.05a$ cat file2 #!/bin/sh -v whoami # dixnei poios eimai #Twra typonoyme tin hmeromhnia date bash-2.05a$./file2 #!/bin/sh -v whoami # dixnei poios eimai asidirop #Twra typonoyme tin hmeromhnia date Mon Nov 20 19:16:30 EET 2006 bash-2.05a$ Αλ αιιάμνπκε ην -v ζε -x, ηφηε ην θέιπθνο δελ ζα εκθαλίδεη φιεο ηηο γξακκέο αιιά κφλν ηηο εληνιέο πνπ πξφθεηηαη λα εθηειεζηνχλ κε έλαλ ζηαπξφ απφ κπξνζηά: bash-2.05a$ cat file2 #!/bin/sh -x whoami # dixnei poios eimai #Twra typonoyme tin hmeromhnia date bash-2.05a$./file2 + whoami asidirop + date Mon Nov 20 19:17:13 EET 2006 179
bash-2.05a$ 8.1.4 Δθηέιεζε ζελαξίσλ θαη ε κεηαβιεηή PATH Γηα λα εθηειέζνπκε έλα πξφγξακκα ή ζελάξην (script) πξέπεη λα αλαθεξζνχκε ζην φλνκα αξρείνπ είηε κε ζρεηηθή είηε κε απφιπηε δηαδξνκή. Έηζη ζην παξαθάησ παξάδεηγκα γηα ην file1 πνπ βξίζθεηαη ζηνλ ηξέρνληα θάθειν εξγαζίαο (cwd) κπνξνχκε είηε λα εθηειέζνπκε./file1, δειαδή λα ρξεζηκνπνηήζνπκε ηε ζρεηηθή δηαδξνκή πξνο ην αξρείν, είηε ~/test/file1, δειαδή λα ρξεζηκνπνηήζνπκε ηελ απφιπηε δηαδξνκή πξνο ην αξρείν. aetos_test_51_$ cat file1 #!/bin/sh whoami date aetos_test_52_$./file1 asidirop Mon Nov 20 18:54:36 EET 2006 aetos_test_53_$ ~/test/file1 asidirop Mon Nov 20 18:54:42 EET 2006 aetos_test_54_$ pwd /usr/people/staff/ektaktoi/it/asidirop/test Αλ δελ δψζνπκε δηαδξνκή γηα ην αξρείν file1, ηφηε ζα πάξνπκε ην κήλπκα ζθάικαηνο: bash-2.05a$./file1 asidirop Mon Nov 20 18:57:17 EET 2006 bash-2.05a$ file1 bash: file1: command not found bash-2.05a$ Απηφ ζπκβαίλεη, δηφηη ην αξρείν-ζελάξην file1 δελ βξίζθεηαη ζε θάπνηνλ θαηάινγν πνπ πεξηέρεηαη ζηε κεηαβιεηή πεξηβάιινληνο PATH. Όπσο αλαθέξακε ζηε Παξάγξαθν 7.3.1 γηα λα κπνξνχκε λα εθηεινχκε έλα πξφγξακκα-εληνιή ρσξίο λα γξάθνπκε ηε δηαδξνκή ζε απηφ, πξέπεη ν θαηάινγνο κέζα ζηνλ νπνίν είλαη απνζεθεπκέλν λα έρεη ζπκπεξηιεθζεί ζηε κεηαβιεηή πεξηβάιινληνο PATH. 8.2 Μεηαβιεηέο Κειύθνπο ην θέιπθνο ππάξρνπλ κεηαβιεηέο (εθηφο ησλ κεηαβιεηψλ πεξηβάιινληνο). Ο ρξήζηεο κπνξεί λα νξίζεη νπνηαδήπνηε κεηαβιεηή. Όιεο νη κεηαβιεηέο είλαη αιθαξηζκεηηθνχ ηχπνπ (string) θαη δελ κπνξεί ν ρξήζηεο λα θαζνξίζεη θάπνηνλ δηαθνξεηηθφ ηχπν. 180
Χο νλόκαηα κεηαβιεηώλ ν ρξήζηεο κπνξεί λα ζέζεη νπνηνλδήπνηε ζπλδπαζκό γξακκάησλ θαη αξηζκώλ (αξρίδνληαο από γξάκκα), ελώ από ηνπο εηδηθνύο ραξαθηήξεο ν κόλνο πνπ κπνξεί λα ρξεζηκνπνηείηαη κε αζθάιεηα είλαη ε ππνγξάκκηζε _. Γελ επηηξέπνληαη θελά θαη άιινη εηδηθνί ραξαθηήξεο πνπ κπνξεί λα έρνπλ θάπνηα εηδηθή ζεκαζία γηα ην θέιπθνο (π.ρ. $ \ # ; θ.ν.θ.). Σν θέιπθνο sh (θαη ην bash) ρεηξίδεηαη ηηο κεηαβιεηέο πεξηβάιινληνο κε ηνλ ίδην ηξφπν πνπ ρεηξίδεηαη ηηο κεηαβιεηέο ηνπ shell. Γηα λα δηαρσξίδνληαη εχθνια, ζπλεζίδεηαη λα ρξεζηκνπνηνχληαη γηα ηηο κεηαβιεηέο πεξηβάιινληνο κφλν θεθαιαίνη ραξαθηήξεο ελψ γηα ηηο κεηαβιεηέο ηνπ θειχθνπο κφλν πεδνί. Οη κεηαβιεηέο ηνπ θειύθνπο απνζεθεύνληαη ζηε κλήκε πνπ ρξεζηκνπνηεί ην ίδην ην shell, είλαη ηνπηθέο θαη δελ θιεξνδνηνύληαη από ηηο δηεξγαζίεο ζηηο ζπγαηξηθέο. Οη κεηαβιεηέο πεξηβάιινληνο απνζεθεύνληαη από ηνλ ππξήλα ζην ρώξν κλήκεο πνπ δηαηεξνύληαη ηα δηάθνξα ζηνηρεία ησλ δηεξγαζηώλ θαη θιεξνδνηνύληαη από ηηο δηεξγαζίεο ζηηο ζπγαηξηθέο ηνπο. Ο νξηζκφο κηαο κεηαβιεηήο γίλεηαη κε ηελ αξρηθνπνίεζε ηεο: a=5 Με ην παξαπάλσ νξίδεηαη ε κεηαβιεηή κε φλνκα a θαη απνζεθεχεηαη ε ηηκή 5 σο αιθαξηζκεηηθφ (string). Απφιπηα ηζνδχλακν κε ην πξνεγνχκελν είλαη θαη ην: a="5" Ππιν και μεηά ηον σαπακηήπα "=" δεν ππέπει να ςπάπσοςν κενά. Δάλ ζηελ ηηκή πξνο εθρώξεζε πεξηέρνληαη εηδηθνί ραξαθηήξεο (πρ: space * ; < > θ.ν.θ.) ηόηε πξέπεη λα ρξεζηκνπνηεζνύλ εηζαγσγηθά (κνλά ή δηπιά) ή λα αλαηξεζεί ε εηδηθή ζεκαζία απηώλ ησλ ραξαθηήξσλ κε ην \ (αλάπνδε θάζεηνο - back slash). 8.2.1 θάικαηα θαηά ηελ εθρώξεζε ηελ πεξίπησζε πνπ πξνζπαζεί ν ρξήζηεο λα θάλεη εθρψξεζε αιιά ρξεζηκνπνηεζνχλ κε ιάζνο ηξφπν ηα θελά δηαζηήκαηα (space), ηφηε πξνθαλψο δελ ζα γίλεη εθρψξεζε, αιιά ζα επηζηξαθεί κήλπκα ζθάικαηνο. asidirop@dellpc:~$ a=5 Β # Δθρώξεζε 1 181
Β: command not found asidirop@dellpc:~$ a="5 Β" # Δθρώξεζε 2 asidirop@dellpc:~$ a= 5 # Δθρώξεζε 3 5: command not found asidirop@dellpc:~$ a=" 5" # Δθρώξεζε 4 asidirop@dellpc:~$ a =5 # Δθρώξεζε 5 a: command not found Παξαπάλσ παξνπζηάδνληαη ηξεηο πεξηπηψζεηο ζθάικαηνο. ηελ πξψηε πεξίπησζε (εθρψξεζε 1) ππάξρεη θελφ δηάζηεκα κεηαμχ ηνπ 5 θαη ηνπ Β. Δθφζνλ ε ηηκή πξνο εθρψξεζε πεξηέρεη θελφ δηάζηεκα, ζα πξέπεη λα ρξεζηκνπνηνχληαη εηζαγσγηθά φπσο ζηελ εθρψξεζε 2. ηελ πεξίπησζε πνπ δελ έρνπλ ρξεζηκνπνηεζεί εηζαγσγηθά, εκθαλίδεηαη ην κήλπκα Β: command not found. Απηφ ζεκαίλεη φηη ην θέιπθνο πξνζπάζεζε λα εθηειέζεη κηα εληνιή κε φλνκα Β ε νπνία φκσο πξνθαλψο δελ βξέζεθε. Απηφ νθείιεηαη ζην φηη ην θέιπθνο ππνζηεξίδεη ηελ εμήο ζχληαμε: ENV_VAR1=VAL1 ENV_VAR2=VAL2... command [args] Με ην παξαπάλσ δίλεηαη ε εληνιή εθηέιεζεο command, φκσο επηπιένλ πξηλ ηελ εθηέιεζή ηεο ηίζεληαη θαη νη κεηαβιεηέο πεξηβάιινληνο ENV_VAR1, ENV_VAR2, θηι. Αθξηβψο ην ίδην ζθάικα ζπκβαίλεη θαη ζηελ επφκελε πεξίπησζε (Δθρψξεζε 3). Σν θέιπθνο πξνζπαζεί λα εθηειέζεη ηελ εληνιή κε φλνκα "5" κε αξρηθνπνίεζε ηεο κεηαβιεηήο πεξηβάιινληνο a ζε θελή ηηκή. Ζ ιχζε πξνθαλψο είλαη ε ρξήζε εηζαγσγηθψλ (εθρψξεζε 4). ηελ ηειεπηαία πεξίπησζε (εθρψξεζε 5) έρεη κπεη θελφ δηάζηεκα πξηλ απφ ηνλ ραξαθηήξα =. Σν κήλπκα ζθάικαηνο απφ ην θέιπθνο είλαη: a: command not found. Δίλαη ζρεδφλ πξνθαλέο πσο εξκήλεπζε ηελ εληνιή ην θέιπθνο. Θεψξεζε φηη δφζεθε ε εληνιή a κε φξηζκα ην "=5". Ππιν και μεηά ηον σαπακηήπα "=" δεν ππέπει να ςπάπσοςν κενά. 8.2.2 Δθρώξεζε ηηκώλ Ζ εθρψξεζε ηηκήο ζε κηα κεηαβιεηή ζην θέιπθνο κπνξεί λα γίλεη κε δπν ηξφπνπο: 1. Αλάζεζε ηηκήο κε εθρψξεζε, φπσο πεξηγξάθεθε παξαπάλσ (πρ: a=543245). 2. Αλάγλσζε ηηκήο απφ ηελ θαλνληθή είζνδν ρξεζηκνπνηψληαο ηελ read. Χξεζηκνπνηώληαο ηελ εληνιή read Ζ εληνιή read εθρσξεί ζε κηα κεηαβιεηή νηηδήπνηε εηζάγεηαη απφ ηελ θαλνληθή είζνδν (ζπλήζσο ην ηεξκαηηθφ), αθνινπζνχκελν απφ κηα αιιαγή γξακκήο, δειαδή δηαβάδεη απφ ην ηεξκαηηθφ κηα γξακκή. 182
bash-2.05a$ read b foo bar bash-2.05a$ echo $b foo bar bash-2.05a$ echo "$b" foo bar bash-2.05a$ ην παξαπάλσ παξάδεηγκα εκθαλίδνπκε κε ππνγξάκκηζε ηελ πιεθηξνιφγεζε ηνπ ρξήζηε. ηε κεηαβιεηή b εθρσξήζεθε αθξηβψο απηφ πνπ πιεθηξνινγήζεθε. Δπεηδή φκσο πεξηέρεη εηδηθνχο ραξαθηήξεο (ηα θελά δηαζηήκαηα), ζα πξέπεη λα ρξεζηκνπνηείηαη κε εηζαγσγηθά. Δίλαη πνιχ ζπλεζηζκέλν θαηά ηελ εθηέιεζε ελφο πξνγξάκκαηνο λα ππάξρεη ε αλάγθε γηα είζνδν απφ ηνλ ρξήζηε. ε απηήλ ηελ πεξίπησζε πξνθαλψο ρξεζηκνπνηείηαη ε εληνιή read. Δίλαη πνιχ θιαζηθφο ζπλδπαζκφο ηεο εληνιήο read κε ηελ echo, φπνπ ε πξψηε εκθαλίδεη ηελ πξνηξνπή γηα ηνλ ρξήζηε: Αρχείο: read_demo #!/bin/bash echo -n "Enter some text > " read text echo "You entered: $text" Παξαθάησ θαίλεηαη ε εθηέιεζε ηνπ ζελαξίνπ read_demo. Ζ ρξήζε ηνπ νξίζκαηνο -n ζηελ εληνιή echo νδεγεί ηελ εληνιή λα κελ αιιάμεη γξακκή κεηά ηελ εκθάληζε ηνπ κελχκαηνο, ζπλεπψο ν θέξζνξαο παξακέλεη ζηελ ίδηα γξακκή θαη ν ρξήζηεο «γξάθεη» ζηελ ίδηα γξακκή κε ηελ πξνηξνπή. Ζ εληνιή ζα δηαβάζεη, ηελ είζνδν κέρξη λα δηαβαζηεί ν ραξαθηήξαο αιιαγήο γξακκήο, ν νπνίνο βέβαηα αληηζηνηρεί ζην πιήθηξν Enter. asidirop@aetos:/tmp$./read_demo Enter some text > My name is Antonis You entered: My name is Antonis asidirop@aetos:/tmp$ 8.2.3 Χξήζε κεηαβιεηώλ Ζ ρξήζε κηαο κεηαβιεηήο (δειαδή ηεο ηηκήο πνπ πεξηέρεη) γίλεηαη ρξεζηκνπνηψληαο ηνλ ραξαθηήξα $. Ο ραξαθηήξαο $ δίλεη ηελ νδεγία ζην θέιπθνο λα ζεσξήζεη ηε ιέμε (string) πνπ αθνινπζεί σο όλνκα κεηαβιεηήο θαη λα ηελ αληηθαηαζηήζεη κε ηελ ηηκή ηεο. 183
asidirop@dellpc:/tmp$ a=hello asidirop@dellpc:/tmp$ echo $a Hello 8.3 Χξήζε Δηζαγσγηθώλ Σν ζχλνιν ραξαθηήξσλ ASCII πεξηέρεη ηξεηο ηχπνπο εηζαγσγηθψλ. Γηα ην θέιπθνο θαη νη ηξεηο ηχπνη εηζαγσγηθψλ έρνπλ εηδηθή ζεκαζία: Σα απιά εηζαγσγηθά ('single quotes') αθπξψλνπλ ηελ εηδηθή ζεκαζία φισλ ησλ ζπκβφισλ εθηφο απφ ηνλ εαπηφ ηνπο. Σα δηπιά εηζαγσγηθά ("double quotes") αθπξψλνπλ ηελ εηδηθή ζεκαζία φισλ ησλ ζπκβφισλ εθηφο απφ ηνλ εαπηφ ηνπο, ηελ αλάπνδε θάζεην (backslash \ ) θαη ην δνιάξην ($). Σα αλάπνδα εηζαγσγηθά (`back quotes`) πξνθαινχλ ηελ εθηέιεζε ηεο εληνιήο πνπ πεξηθιείνπλ. Αθξηβψο ηελ ίδηα ζεκαζία έρνπλ ηα εηζαγσγηθά θαη ζε άιιεο γιψζζεο πξνγξακκαηηζκνχ, νη νπνίεο έρνπλ θιεξνλνκήζεη αξθεηά ραξαθηεξηζηηθά ηνπ θειχθνπο φπσο ε perl θαη ε php. Ζ ρξήζε εηζαγσγηθψλ (κνλά ή δηπιά) είλαη ζρεδφλ ππνρξεσηηθή, φηαλ κέζα ζε έλα αιθαξηζκεηηθφ πεξηιακβάλνληαη εηδηθνί ραξαθηήξεο. Ο πεξηζζφηεξν ζπρλφο εηδηθφο ραξαθηήξαο είλαη ην θελφ δηάζηεκα (space). ην παξαθάησ παξάδεηγκα ε ρξήζε ή φρη εηζαγσγηθψλ ζηηο ηξεηο πξψηεο πεξηπηψζεηο δελ έρεη δηαθνξά. Δίηε ρξεζηκνπνηεζνχλ κνλά εηζαγσγηθά, είηε δηπιά, είηε θαζφινπ, ην απνηέιεζκα είλαη ην ίδην θαη ζσζηφ, εθφζνλ ζην αιθαξηζκεηηθφ δελ πεξηιακβάλεηαη θάπνηνο εηδηθφο ραξαθηήξαο. bash-2.05a$ echo "TEST" TEST bash-2.05a$ echo 'TEST' TEST bash-2.05a$ echo TEST TEST bash-2.05a$ echo "TEST A" TEST A bash-2.05a$ echo 'TEST A' TEST A bash-2.05a$ echo TEST A TEST A bash-2.05a$ echo TEST\ \ \ \ \ A TEST A ηηο ηξεηο επφκελεο εληνιέο ην αιθαξηζκεηηθφ πεξηιακβάλεη πνιιαπιά θελά δηαζηήκαηα (spaces). Γηα ην θέιπθνο (γηα φια ηα θειχθε) ην θελφ δηάζηεκα είλαη εηδηθφο ραξαθηήξαο θαη ζεκαίλεη δηαρσξηζκφο νξηζκάησλ κεηαμχ ηνπο ή δηαρσξηζκφο εληνιήο απφ ηα νξίζκαηα. Μάιηζηα, ην θέιπθνο αγλνεί ηα πνιιαπιά θελά δηαζηήκαηα. Βιέπνπκε, ινηπφλ, ζην παξάδεηγκα φηη ην απνηέιεζκα είλαη ζσζηφ κε ηε ρξήζε εηζαγσγηθψλ (κνλψλ ή δηπιψλ), αιιά φρη αθξηβέο ρσξίο ηε ρξήζε εηζαγσγηθψλ. Οπζηαζηηθά αγλννχληαη (ράλνληαη) ηα πνιιαπιά θελά δηαζηήκαηα. Άξα, ε ρξήζε ησλ εηζαγσγηθψλ είλαη ελδεδεηγκέλε ζηελ πεξίπησζε πνπ ην αιθαξηζκεηηθφ πεξηέρεη έλαλ ή πεξηζζφηεξνπο εηδηθνχο ραξαθηήξεο. ηελ πεξίπησζε πνπ ν ρξήζηεο δελ επηζπκεί ηε ρξήζε ησλ εηζαγσγηθψλ, ηφηε ζα πξέπεη λα αθπξσζεί ε εηδηθή ζεκαζία ησλ εηδηθψλ ραξαθηήξσλ κε ηε ρξήζε ηεο αλάπνδεο θαζέηνπ (back slash). Θα πξέπεη πξηλ απφ θάζε εκθάληζε εηδηθνχ ραξαθηήξα λα ρξεζηκνπνηείηαη ε αλάπνδε θάζεηνο (ηειεπηαία εληνιή). Απηή ε κέζνδνο, βέβαηα, δελ είλαη ηδηαίηεξα πξαθηηθή, εηδηθά φηαλ ππάξρνπλ πνιιέο εκθαλίζεηο εηδηθψλ ραξαθηήξσλ. 184
8.3.1 Δηζαγσγηθά θαη κεηαβιεηέο θειύθνπο Όηαλ ζπκπεξηιακβάλνληαη εηδηθνί ραξαθηήξεο ζηελ ηηκή κηαο κεηαβιεηήο απαηηείηαη πξνζνρή ψζηε λα κελ εξκελεπηνχλ απηνί νη εηδηθνί ραξαθηήξεο. ην παξαθάησ παξάδεηγκα έγηλε εθρψξεζε ζηε κεηαβιεηή a ελφο αιθαξηζκεηηθνχ ην νπνίν πεξηέρεη πνιιαπιά θελά δηαζηήκαηα. Αλ ρξεζηκνπνηεζεί ην $aρσξίο εηζαγσγηθά, ην απνηέιεζκα είλαη ην ίδην κε ηελ πξνεγνχκελε πεξίπησζε, δειαδή θαηαζηξέθνληαη ηα πνιιαπιά θελά δηαζηήκαηα. Θα πξέπεη ινηπφλ θαη νη κεηαβιεηέο λα ρξεζηκνπνηνχληαη κέζα ζε εηζαγσγηθά. Πξνθαλψο, αλ ε κεηαβιεηή δελ πεξηείρε εηδηθνχο ραξαθηήξεο, δελ ζα ππήξρε πξφβιεκα ζηε ρξήζε ηεο θαη ρσξίο εηζαγσγηθά. Όκσο απηφ δελ κπνξεί λα ην γλσξίδεη ν πξνγξακκαηηζηήο εθ ησλ πξνηέξσλ. πλεπψο, κέζα ζε έλα ζελάξην θειχθνπο νη κεηαβιεηέο ζα πξέπεη λα ρξεζηκνπνηνχληαη κέζα ζε δηπιά εηζαγσγηθά. Δδψ λα ζπκίζνπκε φηη κέζα ζηα δηπιά εηζαγσγηθά αθπξψλνληαη φινη νη εηδηθνί ραξαθηήξεο εθηφο απφ ηνπο $, \, ". Άξα, κέζα ζε δηπιά εηζαγσγηθά νη κεηαβιεηέο, νη νπνίεο ζεκαηνδνηνχληαη κε ην $, εξκελεχνληαη. Μέζα ζε κνλά εηζαγσγηθά αθπξψλνληαη όινη νη εηδηθνί ραξαθηήξεο, ζπλεπψο θαη ν ραξαθηήξαο $. bash-2.05a$ a='test 1' # εληνιή 1 bash-2.05a$ echo $a # εληνιή 2 test 1 bash-2.05a$ echo "$a" # εληνιή 3 test 1 bash-2.05a$ echo '$a' # εληνιή 4 $a bash-2.05a$ Μέζα ζε έλα ζελάξην θειύθνπο νη κεηαβιεηέο πξέπεη λα ρξεζηκνπνηνύληαη κέζα ζε δηπιά εηζαγσγηθά. Μάιηζηα, φηαλ ζηηο κεηαβιεηέο πεξηέρνληαη πεξηζζφηεξν «θξίζηκνη» ραξαθηήξεο απφ ην θελφ δηάζηεκα, ηφηε ηα απνηειέζκαηα κπνξεί λα είλαη ηξαγηθά άζηνρα, ελδερνκέλσο θαη θαηαζηξνθηθά γηα ηε ζσζηή ιεηηνπξγία ηνπ ζελαξίνπ θειχθνπο, φπσο ζην παξαθάησ παξάδεηγκα. Δδψ ν εηδηθφο ραξαθηήξαο "*" αληηθαζίζηαηαη κε φια ηα νλφκαηα αξρείσλ ηνπ ηξέρνληνο θαηαιφγνπ (ζπκεζείηε φηη είλαη wildcard - Κεθάιαην 4). bash-2.05a$ a='*' bash-2.05a$ echo $a file1 file5 test8 bash-2.05a$ echo "$a" * bash-2.05a$ Αλ κέζα ζε δηπιά εηζαγσγηθά ζέινπκε λα ρξεζηκνπνηήζνπκε ηνλ ραξαθηήξα $, ρσξίο απηφο λα εξκελεπηεί σο εηδηθφο ραξαθηήξαο, παξάδεηγκα αλ ζέινπκε λα εθηππψζνπκε ην αιθαξηζκεηηθφ "x$x" ηφηε ζα πξέπεη λα αθπξψζνπκε ηελ εηδηθή ζεκαζία ηνπ κε ηε ρξήζε ηεο αλάπνδεο θαζέηνπ (back slash) ή ελαιιαθηηθά λα ρξεζηκνπνηεζνχλ κνλά εηζαγσγηθά: 185
bash-2.05a$ echo "x\$x" x$x bash-2.05a$ echo 'x$x' x$x bash-2.05a$ echo "x$x" x bash-2.05a$ # Με " θαη ρωξίο \$ ην απνηέιεζκα # δελ είλαη ην δεηνύκελν. 8.3.2 Δηζαγσγηθά θαη κεηαβιεηέο πεξηβάιινληνο ηελ πεξίπησζε ησλ κεηαβιεηψλ πεξηβάιινληνο ππάξρεη ε ίδηα ζπκπεξηθνξά θαη πθίζηαηαη ην ίδην πξφβιεκα κε ηηο κεηαβιεηέο ηνπ θειχθνπο. Οη κεηαβιεηέο πεξηβάιινληνο ρξεζηκνπνηνχληαη θαη απηέο κε ηε ρξήζε ηνπ δνιαξίνπ ($). ην παξαθάησ παξάδεηγκα, ε κεηαβιεηή πεξηβάιινληνο HOSTNAME (ε νπνία πεξηέρεη ην φλνκα ππνινγηζηή ζηνλ νπνίν είκαζηε ζπλδεδεκέλνη) εξκελεχεηαη κέζα ζηα δηπιά εηζαγσγηθά αιιά φρη κέζα ζηα κνλά. asidirop@aetos:/tmp$ echo "My host name is $HOSTNAME" My host name is aetos asidirop@aetos:/tmp$ echo 'My host name is $HOSTNAME' My host name is $HOSTNAME asidirop@aetos:/tmp$ 8.3.3 πλέλσζε κεηαβιεηώλ Σν θέιπθνο, φηαλ ζπλαληά ηνλ ραξαθηήξα $, ζεσξεί φηη απηφ πνπ αθνινπζεί είλαη φλνκα κεηαβιεηήο (ή κεηαβιεηήο πεξηβάιινληνο) θαη ην αληηθαζηζηά κε ηελ ηηκή ηνπ. Πνχ φκσο ηειεηψλεη «απηφ πνπ αθνινπζεί»; ε πνην ζεκείν ηειεηψλεη ην φλνκα ηεο κεηαβιεηήο; Σν φλνκα κεηαβιεηήο ηειεηψλεη κφιηο ην θέιπθνο ζπλαληήζεη θάπνηνλ ραξαθηήξα πνπ απαγνξεχεηαη ζηα νλφκαηα κεηαβιεηψλ, δειαδή θάπνηνλ εηδηθφ ραξαθηήξα, ή θελφ δηάζηεκα, ή αιιαγή γξακκήο. Αλ ζέινπκε λα ελψζνπκε δπν αιθαξηζκεηηθά, ην κφλν πνπ ρξεηάδεηαη είλαη λα ηνπνζεηεζεί ην έλα κεηά ην άιιν. Γηα παξάδεηγκα: asidirop@aetos:/tmp$ a='test' asidirop@aetos:/tmp$ b='foo' asidirop@aetos:/tmp$ echo "$a$b" testfoo asidirop@aetos:/tmp$ Ση ζα γίλεη φκσο, αλ ζέισ λα ζπλελψζσ κηα κεηαβιεηή κε κηα ζηαζεξή ζπκβνινζεηξά; asidirop@aetos:/tmp$ a='test' asidirop@aetos:/tmp$ echo "$afoo" asidirop@aetos:/tmp$ 186
ην παξαπάλσ παξάδεηγκα ην θέιπθνο απνηπγράλεη λα ηππψζεη ηε κεηαβιεηή $a θαη ακέζσο κεηά ηε ζπκβνινζεηξά "foo", δηφηη ζεσξεί φηη ην φλνκα ηεο κεηαβιεηήο είλαη afoo. Σέηνηα κεηαβιεηή δελ έρεη νξηζηεί, ζπλεπψο εθηππψλεη θελφ. Τπάξρνπλ πνιιέο ιχζεηο, γηα λα παξαθακθζεί ην παξαπάλσ πξφβιεκα: asidirop@aetos:/tmp$ a='test' asidirop@aetos:/tmp$ echo "$a""foo" testfoo asidirop@aetos:/tmp$ echo "$a"foo testfoo asidirop@aetos:/tmp$ echo "$a"'foo' testfoo asidirop@aetos:/tmp$ echo $a'foo' testfoo asidirop@aetos:/tmp$ #όρη θαιή ιύζε Όιεο νη παξαπάλσ ιχζεηο είλαη ηνπ ηχπνπ WorkAround, δειαδή πξφρεηξε παξάθακςε ηνπ πξνβιήκαηνο. Ζ νξζή θαη γεληθή ιχζε είλαη λα ρξεζηκνπνηνχληαη ηα άγθηζηξα: {}. asidirop@aetos:/tmp$ a='test' asidirop@aetos:/tmp$ echo "${a}foo" testfoo Όπσο έρνπκε αλαθέξεη θαη γηα άιιεο πεξηπηψζεηο, ε νξηνζέηεζε κεηαβιεηήο κε ηα άγθηζηξα είλαη ραξαθηεξηζηηθφ θαη άιισλ γισζζψλ πξνγξακκαηηζκνχ πνπ έρνπλ θιεξνλνκήζεη ραξαθηεξηζηηθά απφ ην θέιπθνο, φπσο ε php θαη ε perl. Ο θαιύηεξνο ηξόπνο, γηα λα ρξεζηκνπνηεζεί κηα κεηαβιεηή a, είλαη λα ρξεζηκνπνηείηαη κέζα ζε δηπιά εηζαγσγηθά θαη άγθηζηξα "${a}". 8.3.4 Σα αλάπνδα εηζαγσγηθά ` θαη ην $() Σα αλάπνδα εηζαγσγηθά εθηεινχλ ηε ζπκβνινζεηξά πνπ πεξηέρνπλ σο εληνιή, δελ εκθαλίδεηαη ηίπνηα ζηελ θαλνληθή έμνδν θαη «επηζηξέθνπλ» ζαλ θιήζε ζπλάξηεζεο φ,ηη έρεη ζηείιεη ε εληνιή ζηελ έμνδφ ηεο. asidirop@aetos:~$ date Mon Jul 27 10:54:27 EEST 2015 asidirop@aetos:~$ a=`date` asidirop@aetos:~$ echo "$a" Mon Jul 27 10:54:32 EEST 2015 asidirop@aetos:~$ echo "$a" Mon Jul 27 10:54:32 EEST 2015 asidirop@aetos:~$ Γηα παξάδεηγκα ε εληνιή date εκθαλίδεη ζηελ θαλνληθή έμνδν ηελ ηξέρνπζα εκεξνκελία θαη ψξα. Αλ γίλεη αλάζεζε ηεο date κε αλάπνδα εηζαγσγηθά ζε κηα κεηαβιεηή a, ηφηε ε κεηαβιεηή ζα πεξηέρεη απηφ πνπ 187
έζηεηιε ε εληνιή ζηελ θαλνληθή έμνδν ηελ ψξα ηεο αλάζεζεο. Πξνθαλψο, φζεο θνξέο θαη λα εκθαλίζνπκε ηε κεηαβιεηή ζα πεξηέρεη ηελ ψξα θαηά ηε ζηηγκή ηεο αλάζεζεο θαη φρη ηελ ψξα θαηά ηε ζηηγκή ηεο ρξήζεο. Γειαδή ε εληνιή έρεη εθηειεζηεί κηα θνξά θαηά ηε ζηηγκή ηεο αλάζεζεο. Δπηπιένλ, κέζα ζηα αλάπνδα εηζαγσγηθά κπνξεί λα ζπκπεξηιεθζεί νπνηνζδήπνηε ζπλδπαζκφο εληνιψλ κε δηαζσιήλσζε, αλαθαηεχζπλζε θαη νηηδήπνηε άιιν ζα κπνξνχζε λα γξαθηεί ζηε γξακκή εληνιψλ. ηελ πξαγκαηηθφηεηα, φηαλ ην θέιπθνο βξεη αλάπνδα εηζαγσγηθά δεκηνπξγεί έλα λέν θέιπθνο (δηεξγαζία), ην νπνίν είλαη ππεχζπλν λα εθηειέζεη ηηο εληνιέο πνπ πεξηθιείνληαη ζηα εηζαγσγηθά. Ζ θαλνληθή έμνδνο απφ ην λέν θέιπθνο δεζκεχεηαη θαη γίλεηαη αλάζεζε ζηε κεηαβιεηή. Όιεο νη εληνιέο πνπ ζα εθηειεζηνχλ απφ ην λέν θέιπθνο, θιεξνλνκνχλ ηελ θαλνληθή έμνδν ηνπ λένπ θειχθνπο. asidirop@aetos:~$ a=`ls wc` asidirop@aetos:~$ echo "$a" 33 33 257 asidirop@aetos:~$ Ζ έμνδνο ησλ εληνιψλ κέζα ζηα αλάπνδα εηζαγσγηθά κπνξεί λα πεξηέρεη πνιιέο γξακκέο, φπσο γηα παξάδεηγκα ε έμνδνο απφ ηελ εληνιή ls -l: bash-2.05a$ b=`ls -l` bash-2.05a$ echo $b total 32 -rw-r--r-- 1 asidirop it 314 Jan 11 2003 cc -rwxr--r-- 1 asidirop it 77 Nov 20 19:17 file1 -rwxr-xr-x 1 asidirop it 61 Nov 20 19:34 file2 -rw-r--r-- 1 asidirop it 183 Jan 8 2003 list bash-2.05a$ echo "$b" total 32 -rw-r--r-- 1 asidirop it 314 Jan 11 2003 cc -rwxr--r-- 1 asidirop it 77 Nov 20 19:17 file1 -rwxr-xr-x 1 asidirop it 61 Nov 20 19:34 file2 -rw-r--r-- 1 asidirop it 183 Jan 8 2003 list bash-2.05a$ Όκσο γηα λα ρξεζηκνπνηήζνπκε ην απνηέιεζκα, ζα πξέπεη πάληα λα ρξεζηκνπνηνχληαη δηπιά εηζαγσγηθά γηα ηε κεηαβιεηή, δηφηη δηαθνξεηηθά, φπσο θαίλεηαη παξαπάλσ, ράλνληαη νη εηδηθνί ραξαθηήξεο (πνιιαπιά θελά, αιιαγή γξακκήο θ.ν.θ.). ην θέιπθνο bash ηελ ίδηα ρξήζε κε ηα αλάπνδα εηζαγσγηθά έρεη θαη ν ζπλδπαζκφο $(). Πξαθηηθά είλαη ηζνδχλακα κε ηα αλάπνδα εηζαγσγηθά: bash-2.05a$ b=$(ls l) bash-2.05a$ echo "$b" total 32 -rw-r--r-- 1 asidirop it 314 Jan 11 2003 cc -rwxr--r-- 1 asidirop it 77 Nov 20 19:17 file1 -rwxr-xr-x 1 asidirop it 61 Nov 20 19:34 file2 -rw-r--r-- 1 asidirop it 183 Jan 8 2003 list bash-2.05a$ 188
Υξεηάδεηαη ηδηαίηεξε πξνζνρή! Όηαλ ζε έλα θέιπθνο ρξεζηκνπνηνύληαη δπλαηόηεηεο ηνπ bash νη νπνίεο δελ ππνζηεξίδνληαη από ην sh, ζα πξέπεη νπσζδήπνηε ην ζελάξην λα μεθηλά κε #!/bin/bash θαη όρη κε #!/bin/sh. 8.4 Αξηζκεηηθέο Πξάμεηο 8.4.1 Αξηζκεηηθέο Πξάμεηο κε ρξήζε ηεο expr Γεληθά ηα θειχθε δελ ππνζηεξίδνπλ κεηαβιεηέο ηχπνπ αξηζκνχ θαη ζπλεπψο δελ ππνζηεξίδνπλ αξηζκεηηθέο πξάμεηο (ην bash φκσο ππνζηεξίδεη: βιέπε Παξάγξαθν 8.4.2). Οη αξηζκεηηθέο πξάμεηο πξαγκαηνπνηνχληαη κε ηε ρξήζε εμσηεξηθψλ εληνιψλ. Ζ πην δηαδεδνκέλε εληνιή γηα αξηζκεηηθέο πξάμεηο είλαη ε expr. Ζ expr έρεη ηε δπλαηφηεηα λα πξαγκαηνπνηεί κφλν πξάμεηο αθέξαησλ αξηζκψλ. Γέρεηαη σο νξίζκαηα ηελ αξηζκεηηθή παξάζηαζε θαη ηππψλεη ην απνηέιεζκα ζηελ θαλνληθή έμνδν. asidirop@aetos:~$ expr 1 + 2 3 asidirop@aetos:~$ a=5 asidirop@aetos:~$ expr "$a" - 10-5 asidirop@aetos:~$ b=4000 asidirop@aetos:~$ expr "$b" + "$a" 4005 asidirop@aetos:~$ Πξνθαλψο ζηα νξίζκαηα ηεο expr κπνξνχλ λα δνζνχλ είηε ζηαζεξέο ηηκέο αξηζκψλ είηε κεηαβιεηέο ζηηο νπνίεο πξνεγνχκελα έρεη γίλεη αλάζεζε αξηζκεηηθή ηηκή. Απαηηείηαη αξθεηή πξνζνρή, φηαλ ρξεζηκνπνηείηαη ε εληνιή expr ζηνλ ηξφπν κε ηνλ νπνίν ζα δνζνχλ ηα νξίζκαηα θαζψο θαη ζηελ πξάμε ηνπ πνιιαπιαζηαζκνχ. asidirop@aetos:~$ expr 6 * 10 # εληνιή 1 expr: syntax error asidirop@aetos:~$ expr 6 \* 10 # εληνιή 2 60 asidirop@aetos:~$ expr 6 '*' 10 # εληνιή 3 60 asidirop@aetos:~$ expr "6 * 10" # εληνιή 4 6 * 10 asidirop@aetos:~$ Δθφζνλ ε πξάμε ηνπ πνιιαπιαζηαζκνχ ζπκβνιίδεηαη κε ηνλ ραξαθηήξα *, ν νπνίνο φκσο είλαη θαη εηδηθφο ραξαθηήξαο γηα ην θέιπθνο, ζα πξέπεη λα αθπξσζεί ε εηδηθή ηνπ ζεκαζία. Γηαθνξεηηθά, φπσο θαίλεηαη ζηελ πξψηε εληνιή παξαπάλσ ε expr ζα δψζεη ζπληαθηηθφ ζθάικα, δηφηη ην "*" ζα έρεη αληηθαηαζηαζεί απφ ην θέιπθνο, πξηλ εθηειεζηεί ε expr κε ηα νλφκαηα αξρείσλ ηνπ ηξέρνληνο θαηαιφγνπ. ηε δεχηεξε θαη ηξίηε εληνιή παξαπάλσ, έρεη αθπξσζεί ε εηδηθή ζεκαζία ηνπ "*", ζηε κηα κε ηελ αλάπνδε θάζεην ελψ ζηελ άιιε κε ηα εηζαγσγηθά. Πξνζνρή φκσο (ηέηαξηε εληνιή) δελ ζα κπνξνχζακε λα βάινπκε ζε εηζαγσγηθά νιφθιεξε ηελ αξηζκεηηθή παξάζηαζε. Ζ expr απαηηεί θάζε ηειεζηήο θαη ηειεζηένο λα απνηειεί δηαθνξεηηθφ φξηζκα ζηελ εληνιή. 189
Δθφζνλ ε expr ζηέιλεη ην απνηέιεζκα ζηελ θαλνληθή έμνδν, κπνξνχκε λα δεζκεχζνπκε ηελ θαλνληθή έμνδν κε ηε ρξήζε ησλ αλάπνδσλ εηζαγσγηθψλ θαη λα ηελ εθρσξήζνπκε ζε θάπνηα κεηαβιεηή. asidirop@aetos:~$ c=`expr 7 / 2` asidirop@aetos:~$ echo "$c" 3 asidirop@aetos:~$ a=4000 asidirop@aetos:~$ b=5 asidirop@aetos:~$ d=`expr "$a" + "$b"` asidirop@aetos:~$ echo "$d" 4005 asidirop@aetos:~$ Ο πξνεγνχκελνο, ινηπφλ, είλαη ν γεληθφο ηξφπνο ρξήζεο ηεο expr ζε φια ηα θειχθε. Όκσο ρξεηάδεηαη ηδηαίηεξε πξνζνρή θαηά ηε ρξήζε. ην παξαθάησ παξάδεηγκα θαίλνληαη δπν πνιχ ζπλεζηζκέλεο πεξηπηψζεηο ζθάικαηνο. ηελ πξψηε πεξίπησζε νιφθιεξε ε αξηζκεηηθή παξάζηαζε απνηειεί έλα θαη κφλν φξηζκα, θάηη πνπ δελ έρεη ηε δπλαηφηεηα λα ην δηαρεηξηζηεί ε expr. ηε δεχηεξε πεξίπησζε δελ δηαρσξίδεηαη ε πξάμε απφ ηνλ δεχηεξν αξηζκφ, ζπλεπψο ε εληνιή ζεσξεί ην "+" σο πξφζεκν ηνπ δεχηεξνπ αξηζκνχ, άξα ιείπεη ε πξάμε. Σν απνηέιεζκα θαη ζηηο δπν πεξηπηψζεηο είλαη εζθαικέλν. asidirop@aetos:~$ expr 6+4 6+4 asidirop@aetos:~$ expr 6 +4 expr: syntax error asidirop@aetos:~$ Δπίζεο, πξφβιεκα κπνξεί λα δεκηνπξγεζεί θαη ζηηο πεξηπηψζεηο πνπ ρξεζηκνπνηνχληαη κεηαβιεηέο, αιιά απηέο δελ έρνπλ αξρηθνπνηεζεί. ηα παξαθάησ παξαδείγκαηα, ζηελ πξψηε πεξίπησζε, έρεη αξρηθνπνηεζεί ε κεηαβιεηή a αιιά φρη ε w. πλεπψο, ε εληνιή expr $a + $w είλαη ζαλ λα έρνπκε γξάςεη expr 1 +, ην νπνίν πξνθαλψο είλαη ιαλζαζκέλε αξηζκεηηθή παξάζηαζε. Αθφκε θαη αλ ρξεζηκνπνηεζνχλ εηζαγσγηθά (εληνιή ηξίηε), ην ηξίην φξηζκα ("$w") ζα είλαη θελφ (empty string), ην νπνίν ε expr δελ κπνξεί λα ην κεηαηξέςεη ζε αξηζκφ. bash-2.05a$ a=1 bash-2.05a$ expr $a + $w # πεξίπηωζε 1 Syntax error bash-2.05a$ expr 1 + # πεξίπηωζε 2 Syntax error bash-2.05a$ expr "$a" + "$w" # πεξίπηωζε 3 non-numeric argument bash-2.05a$ expr 0"$a" + 0"$w" # πεξίπηωζε 4 1 bash-2.05a$ b=x bash-2.05a$ expr 0"$a" + 0"$b" # πεξίπηωζε 5 expr: non-integer argument bash-2.05a$ k=`expr $c + $w` # πεξίπηωζε 6 Syntax error bash-2.05a$ echo $k 190
bash-2.05a$ Μηα πξφρεηξε παξάθακςε ηνπ πξνβιήκαηνο κπνξεί λα γίλεη ρξεζηκνπνηψληαο ην "0" πξηλ απφ θάζε κεηαβιεηή, έηζη ψζηε, αλ ε κεηαβιεηή είλαη θελή ν ηειεζηένο λα είλαη "0", αλ δελ είλαη θελή, παξάδεηγκα "1", ν ηειεζηένο ζα είλαη "01", δειαδή αξηζκεηηθά "1". Παξφια απηά, πάιη κπνξνχλ λα πξνθχςνπλ ζθάικαηα ζηελ πεξίπησζε πνπ κηα κεηαβιεηή δελ πεξηέρεη αξηζκφ αιιά ραξαθηήξεο (πεξίπησζε 5). Σέινο, ηα πξνβιήκαηα κπνξνχλ λα πνιιαπιαζηαζηνχλ, φηαλ γίλεηαη αλάζεζε ηνπ απνηειέζκαηνο ζε κεηαβιεηή, αιιά ε θιήζε ηεο expr έδσζε θάπνην ζθάικα φπσο ζηελ πεξίπησζε 6. Ζ εληνιή δελ ζα ηππψζεη ηίπνηε ζηελ θαλνληθή έμνδν, ζπλεπψο ε κεηαβιεηή ζα έρεη θελή ηηκή. Άξα, φηαλ ζα ηε ρξεζηκνπνηήζνπκε αξγφηεξα ζην ζελάξην ζα δεκηνπξγήζεη πξφβιεκα. Πξηλ από ηε ρξήζε ηεο expr απαηηείηαη νπσζδήπνηε έιεγρνο θαη επηβεβαίσζε λόκηκσλ ηηκώλ ησλ κεηαβιεηώλ. Δλαιιαθηηθά, κεηά από ηε ρξήζε ηεο expr απαηηείηαη νπσζδήπνηε έιεγρνο θαη επηβεβαίσζε ηνπ απνηειέζκαηνο ή ηνπ θσδηθνύ ζθάικαηνο (error code ή exit code). 8.4.2 Αξηζκεηηθέο Πξάμεηο κε ρξήζε ηεο αξηζκεηηθήο θαηάζηαζεο (arithmetic mode) ηνπ bash Σν bash (σο επέθηαζε ηνπ sh) έρεη ηε δπλαηφηεηα λα θάλεη αξηζκεηηθέο πξάμεηο. Δπηπιένλ: Γελ ππάξρεη πξφβιεκα κε ηα θελά δηαζηήκαηα (spaces). Γελ ππάξρεη πξφβιεκα, αλ κηα κεηαβιεηή δελ είλαη νξηζκέλε (αξθεί λα κελ ρξεζηκνπνηνχκε ην $). Γελ ππάξρεη πξφβιεκα, αλ κηα κεηαβιεηή δελ πεξηέρεη αξηζκφ (ζεσξείηαη 0). asidirop@aetos:~$ a=$((5+4)) # πεξίπηωζε 1 asidirop@aetos:~$ echo $a 9 asidirop@aetos:~$ a=$((a+4)) # πεξίπηωζε 2 asidirop@aetos:~$ echo $a 13 asidirop@aetos:~$ a=$((a+w)) # πεξίπηωζε 3 asidirop@aetos:~$ echo $a 13 asidirop@aetos:~$ a=$((a+$w)) # πεξίπηωζε 4 -bash: a+: syntax error: operand expected (error token is "+") asidirop@aetos:~$ asidirop@aetos:~$ w='test' asidirop@aetos:~$ a=$((a+w)) # πεξίπηωζε 5 asidirop@aetos:~$ echo $a 13 ην παξαπάλσ παξάδεηγκα βιέπνπκε (πεξηπηψζεηο 1 θαη 2) φηη δελ ππάξρεη πξφβιεκα κε ηε κε χπαξμε θελψλ δηαζηεκάησλ κέζα ζηελ αξηζκεηηθή παξάζηαζε. ηελ πεξίπησζε 3, πνπ ρξεζηκνπνηείηαη ε κεηαβιεηή w, ε νπνία δελ έρεη νξηζηεί, ρξεζηκνπνηείηαη ζαλ κεδέλ (0). Όκσο αλ είρακε βάιεη ηνλ 191
ραξαθηήξα $ πξηλ απφ ηε κεηαβιεηή w, ηφηε, φπσο θαίλεηαη ζηελ πεξίπησζε 4, ππάξρεη πξφβιεκα. Σέινο, αλ κηα κεηαβιεηή πεξηέρεη γξάκκαηα θαη φρη αξηζκφ, ηφηε κεηαθξάδεηαη ζε κεδέλ (πεξίπησζε 5). Υξεηάδεηαη κεγάιε πξνζνρή ζηελ πεξίπησζε πνπ ρξεζηκνπνηεζεί ν ραξαθηήξαο $ κέζα ζε αξηζκεηηθή παξάζηαζε σο κεηαβιεηή. asidirop@aetos:~$ a=13 asidirop@aetos:~$ b='test' asidirop@aetos:~$ test='1000' asidirop@aetos:~$ c=$(($a+$b)) asidirop@aetos:~$ echo $c 1013 asidirop@aetos:~$ To $ εξκελεχεηαη πξηλ απφ ηελ εθηέιεζε ηεο πξάμεο. Άξα, ην $b ζα αληηθαηαζηαζεί κε ην test θαη ην $a κε ην 13. Άξα, είλαη ζαλ λα γξάθνπκε:c=$((13+test)) θαη ην test είλαη κεηαβιεηή πνπ πεξηέρεη ηελ ηηκή 1000! Πξνηηκήζηε ηε δπλαηόηεηα ηνπ bash γηα αξηζκεηηθέο πξάμεηο, αξθεί ην ζελάξην λα μεθηλάεη κε #!/bin/bash Απνθύγεηε ηε ρξήζε ηνπ $ κέζα ζηελ θαηάζηαζε αξηζκεηηθήο ιεηηνπξγίαο (arithmetic mode). Σέινο, λα ζεκεησζεί φηη ε θαηάζηαζε αξηζκεηηθήο ιεηηνπξγίαο ππνζηεξίδεη φιεο ηηο καζεκαηηθέο πξάμεηο θαη φιεο ηηο ζπληνκνγξαθίεο πνπ ηζρχνπλ ζηηο πεξηζζφηεξεο γιψζζεο πξνγξακκαηηζκνχ (Πίλαθα 8.1). Γηα παξάδεηγκα: asidirop@aetos:~$ a=13 asidirop@aetos:~$ ((a++)) asidirop@aetos:~$ echo $a 14 asidirop@aetos:~$ ((a+=6)) asidirop@aetos:~$ echo $a 20 asidirop@aetos:~$ ((b=a+8)) asidirop@aetos:~$ c=$((a+8)) asidirop@aetos:~$ echo $b 28 asidirop@aetos:~$ echo $c 28 asidirop@aetos:~$ Όπσο θαίλεηαη ζηα παξαπάλσ παξαδείγκαηα, αλάζεζε ηηκήο ζε κεηαβιεηή κπνξεί λα γίλεη εμνινθιήξνπ κέζα ζηελ θαηάζηαζε αξηζκεηηθήο ιεηηνπξγίαο, δειαδή ην ((b=a+8)). Πξνζνρή, ζε απηήλ ηελ πεξίπησζε δελ ρξεζηκνπνηείηαη ν ραξαθηήξαο $ πξηλ απφ ηηο παξελζέζεηο. 192
Πίλαθαο 8.1: Λίζηα κε ηηο αξηζκεηηθέο πξάμεηο ηεο θαηάζηαζεο αξηζκεηηθήο ιεηηνπξγίαο ηνπ θειύθνπο. id++ id-- ++id --id Πξάμε Δμήγεζε variable post-increment and post-decrement variable pre-increment and pre-decrement - + unary minus and plus! ~ logical and bitwise negation ** exponentiation *,/, % multiplication, division, remainder +, - addition, subtraction <<, >> left and right bitwise shifts <=,>=, <, > comparison ==,!= equality and inequality &, ^, &&, expr?expr:expr = *= /= %= += -= <<= >>= &= ^= = bitwise AND, bitwise exclusive OR, bitwise OR logical AND, logical OR conditional operator assignment 8.5 Αζθήζεηο γηα εμάζθεζε ηόρνο Δηζαγσγή ζηα ζελάξηα θινηνχ Άζθεζε 1 Φηηάμηε έλα ζελάξην θειχθνπο κε φλνκα myls, ην νπνίν ζα εθηειεί ηελ εληνιή ls l (ζα εκθαλίδεη ηα απνηειέζκαηά ηεο), κεηά ζα εκθαλίδεη ην πιήζνο ησλ απιψλ αξρείσλ, ην πιήζνο ησλ θαηαιφγσλ, ην πιήζνο ησλ θξπθψλ αξρείσλ, ην πιήζνο ησλ θξπθψλ θαηαιφγσλ. 193
Άζθεζε 2 Γεκηνπξγήζηε έλα script κε φλνκα echo_test ην νπνίν λα πεξηέρεη: Αρχείο: echo_test #!/bin/sh #echo_test #----------------------------------- echo "1.the process id is : $$ and cwd $PWD" echo '2.the process id is : $$ and cwd $PWD ' echo 3.the process id is : $$ and cwd $PWD echo 4.the process id is\ \ :\ \ \ \$\$ and cwd $PWD echo '5.the process id is : "$$ and cwd $PWD" ' echo "6.the process id is : '$$' and cwd $PWD" Ση παξαηεξείηε θαηά ηελ εθηέιεζή ηνπ; Άζθεζε 3 Γεκηνπξγήζηε έλα ζελάξην θειχθνπο κε φλνκα echo_test3 ην νπνίν λα πεξηέρεη: Αρχείο: echo_test3 #!/bin/bash #echo_test3 #----------------------------------- a=test b=test B c="test C" d="$c + D" echo "1.a is $a" echo echo "2.b is $b" echo echo '3.c is $c' echo "4.c is $c" echo 5.c is $c echo echo "5.d is $d" echo var1="6 " var2=$((var1 + 2 )) echo "7.var1 is $var1, var2 is $var2" 1. Ση παξαηεξείηε; Πνηεο είλαη νη δηαθνξέο κε ηε ρξήζε δηπιψλ ή κνλψλ εηζαγσγηθψλ; 2. Πνηα ηηκή έρεη ε κεηαβιεηή b; 194
Άζθεζε 4 Γεκηνπξγήζηε ηα παξαθάησ ζελάξηα θειχθνπο θαη εθηειέζηε ηα. Πνην είλαη ην θαιχηεξν; Αρχείο: echo_test4a #!/bin/sh #echo_test4a #----------------------------------- x=`ls l` echo x is $x Αρχείο: echo_test4b #!/bin/sh #echo_test4b #----------------------------------- x=`ls l` echo "x is $x" Αρχείο: echo_test4c #!/bin/sh #echo_test4c #----------------------------------- x=`ls l` echo 'x is $x' 195
Άζθεζε 5 Γεκηνπξγήζηε έλα ζελάξην θειχθνπο κε φλνκα echo_test5 ην νπνίν λα πεξηέρεη: Αρχείο: echo_test5 #!/bin/bash #echo_test5 #----------------------------------- a=5 b=" 6" c="" d=$((a+5)) e=$((b+5)) ((f=c+5)) echo "d is $d, e is $e, f is $f" echo d=`expr $a + 5` e=`expr $b+5` f=`expr $c+5` echo "d is $d, e is $e, f is $f" Άζθεζε 6 Γεκηνπξγήζηε έλα ζελάξην θειχθνπο κε φλνκα echo_test6 ην νπνίν λα πεξηέρεη: Αρχείο: echo_test6 #!/bin/sh #script06 #----------------------------------- a=5 echo n "Give me your name: " read name echo "value of a is $a" echo "value of name is $name" Άζθεζε 7 Γεκηνπξγήζηε ην παξαθάησ ζελάξην θειχθνπο: Αρχείο: echo_test7 #!/bin/sh #echo_test7 #----------------------------------- echo "first parameter : $1" echo "third parameter : $3" 196
echo "ninth parameter : $9" echo "tenth parameter : $10" echo "eleventh parameter : $11" echo "No of parameters : $#" echo "all parameters : $*" echo "all parameters : $@" shift echo "first parameter : $1" echo "all parameters : $*" ηνλ Πίλαθα 8.2 εμεγνχληαη νη πξνδεισκέλεο κεηαβιεηέο ηνπ θειχθνπο. Ση ζα εκθαληζηεί ζηελ νζφλε κε ηελ εθηέιεζε ηεο αθφινπζεο γξακκήο εληνιήο;./echo_test7 one two 3 4 5 6 7 eight 9 ten 11 Πίλαθαο 8.2: Πξν-δεισκέλεο κεηαβιεηέο ηνπ θειύθνπο. Μεηαβιεηή Δμήγεζε $1,$2, $9 νη ηηκέο ησλ 9 πξψησλ νξηζκάησλ πνπ έδσζε ν ρξήζηεο ζε έλα script $# ην πιήζνο ησλ νξηζκάησλ πνπ έδσζε ν ρξήζηεο ζε έλα script $*, $@ Οη πίλαθεο κε ηα νξίζκαηα πνπ έδσζε ν ρξήζηεο ζε έλα script $$ Σν ProcessID ηνπ ηξέρνληνο shell 197