ΕΠΛ371 - Πξνγξακκαηηζκόο πζηεκάηωλ Γηάιεμε 7 Εξγαιεία Ωθειηκόηεηαο Unix: Αwk Γεκήηξεο Εετλαιηπνύξ 7-1
Δπεμεξγαζία Ρεύκαηνο sed (Stream EDitor) awk (Alfred Aho, Peter Weinberger, and Brian Kernighan) Γεκηνπξγείηαη ζηα Bell Labs από ηνλ ηδξπηή ηεο γιώζζαο C θαη ηνπ UNIX. Ζ πην ηζρπξή ηεο έθδνζε νλνκάδεηαη Perl o Larry Wall, δεκηνπξγόο ηεο Perl, εκπλέεηαη από ηελ awk. Σημείφζη: Μελεηήζηε ηα εγτειρίδια ποσ σπάρτοσν ζηην ιζηοζελίδα και ηο man ζηο UNIX. 7-2
Δηζαγσγή ζηελ awk Μηα γιώζζα πξνγξακκαηηζκνύ ζρεδηαζκέλε γηα λα βξίζθεη, ηαηξηάδεη πξόηππα θαη λα εθηειεί ελέξγεηεο ζε αξρεία ξεύκαηα εηζόδνπ. παίξλεη είζνδν από αξρεία, αλαθαηεύζπλζε, δηνρέηεπζε θαη απεπζείαο από ην πξνθαζνξηζκέλν ξεύκα εηζόδνπ 7-3
Δηζαγσγή ζηελ awk Τπάξρνπλ πνιινί ηξόπνη λα ηξέμνπκε έλα awk πξόγξακκα awk 'program' input_file(s) program θαη input files παρέτονηαι ως ορίσματα γραμμής εντολής awk 'program' program είλαη έλα όξηζκα γξακκήο εληνιήο. Ζ είζνδνο δίλεηαη από ην πξνθαζνξηζκέλν ξεύκα εηζόδνπ ή από δηνρέηεπζε awk -f program_file input_files program δηαβάδεηαη από αξρείν 7-4
Λνγηθή Δπεμεξγαζίαο ηεο awk Πεξηγξαθή ηεο AWK από ηνλ Alfred V. Aho (έλα από ηνπο δεκηνπξγνύο ηεο AWK): Ζ AWK είλαη γιώζζα γηα επεμεξγαζία αξρείσλ θεηκέλνπ. Έλα αξρείν επεμεξγάδεηαη σο κηα αθνινπζία εγγξαθώλ (records), θαη εμ νξηζκνύ θάζε γξακκή είλαη έλα record. Κάζε γξακκή ηέκλεηαη ζε πεδία (fields). Έλα AWK πξόγξακκα είλαη κηα αθνινπζία (sequence) από εθθξάζεηο pattern-action. Σν AWK δηαβάδεη από ην input κηα γξακκή θάζε θνξά θαη γηα θάζε γξακκή εμεηάδεηαη ην θάζε pattern μερωξηζηά. Γηα θάζε pattern πνπ ηαηξηάδεη εθηειείηαη ην αληίζηνηρν action. 7-5
Λνγηθή Δπεμεξγαζίαο ηεο awk Εγγξαθέο (Records) $NR (seen so far) Ρνή Εηζόδνπ ζηελ AWK $1 $2 $3 $NF ΣΔΥΣ<FS>ΣΔΥΣ<FS>TEXT<FS>TEXT<RS> ΣΔΥΣ<FS>ΣΔΥΣ<FS>TEXT<RS> $NF ΣΔΥΣ<FS>ΣΔΥΣ<RS> ΣΔΥΣ<FS>ΣΔΥΣ<FS>TEXT<RS> Πεδία (Fields) $NF $NF $0: complete line FS: Input File Separator (space by default) RS: Record Separator (newline by default) NR: Number of Records seen so far in input NF: Number of Fields in current input record 7-6
Λνγηθή Δπεμεξγαζίαο ηεο awk Ρνή Εμόδνπ από ηελ AWK text<οfs>text<οfs>text<ofs>text<ors> OFS: Output File Separator (space by default) ORS: Output Record Seperator (newline by default) 7-7
Γνκή Πξνγξάκκαηνο awk (Παξάδεηγκα Δθηέιεζεο) Παξάδεηγκα > ls -al total 17600 drwxr-xr-x 2 dzeina faculty 4096 May 5 2009. drwxr-xr-x 10 dzeina faculty 4096 Jan 14 15:55.. -rw-r--r-- 1 dzeina faculty 967047 Feb 1 01:53 01.pdf -rw-r--r-- 1 dzeina faculty 519830 Feb 1 01:53 02.pdf -rw-r--r-- 1 dzeina faculty 432031 Feb 1 01:54 03.pdf -rw-r--r-- 1 dzeina faculty 738217 Feb 2 13:56 04.pdf Εθηύπωζε 3 εο θαη 4 εο ζηήιεο (όπωο όκνην κε ηελ ls -al cut -d" " -f4,5) > ls al awk -F" " '{print $3" "$4}' dzeina faculty dzeina faculty dzeina faculty dzeina faculty dzeina faculty dzeina faculty 7-9
Γνκή Πξνγξάκκαηνο awk (Εεύγε Pattern {Action}) Όπσο αλαθέξακε, ε awk ζαξώλεη ηηο γξακκέο εηζόδνπ κηα-κηα, ςάρλνληαο λα δεη πνηα γξακκή ηαηξηάδεη κε έλα ζύλνιν πξνηύπωλ (patterns) ή ζπλζεθώλ (conditions) πνπ δίλνληαη ζηελ awk. Γηα θάζε pattern, πξνζδηνξίδεηαη κηα πξάμε (action). H πξάμε εθηειείηαη όηαλ ην πξόηππν ηαηξηάδεη απηό ηνπ input line. awk <options> pattern { action }; pattern { action } Σα Actions ζπκπεξηιακβάλνληαη κέζα ζε curly παξελζέζεηο θαη δηαρσξίδνληαη κε semi-colon ; 7-10
Γνκή Πξνγξάκκαηνο awk (Eπηινγέο Options) awk <options> pattern { action }; pattern { action } Τπάξρνπλ θαπνηα POSIX options (κε -) θαη θαπνηα άιια GNU options (κε --) Οη πεξηζζόηεξεο επηινγέο δε ζα είλαη πνιύ ρξήζηκεο ζηα πιαίζηα ηνπ καζήκαηνο. Κάπνηεο ρξήζηκεο επηινγέο είλαη νη αθόινπζεο: -F fs : Πξνζδηνξηζκόο ηνπ Field Separator από ην command line. Π.ρ., ls -al awk -F"." '{print $2}. Δλαιιαθηηθά κπνξεί λα πξνζδηνξηζηεί ζην ΒΔGIN block πνπ ζα δνύκε ζε ιίγν! -W help: Δθηύπσζε κηαο ζύλνςεο επίινγσλ. -f program-file: Αλάγλσζε πξνγξάκκαηνο ηεο sed από αξρείν (ζην νπνίν πεξηέρεηαη έλα pattern-action αλά γξακκή). Δπίζεο πνιιαπιά αξρεία κπνξνύλ λα πξνζδηνξηζηνύλ κε -f 7-11
Γνκή Πξνγξάκκαηνο awk ('pattern {action} ) ην πξνεγνύκελν παξάδεηγκα ΔΕΝ ππήξρε ην pattern. Τπήξρε απιά ην action: awk '{print $3"\t"$4}' Απηό ππνδήισλε όηη ην action ζα έπξεπε λα εθηειείηαη ζε θάζε γξακκή εηζόδνπ. Ήηαλ δειαδή αληίζηνηρν ηεο αθόινπζεο εληνιήο (όπνπ ην 1 ππνδειώλεη ην pattern TRUE, δει., ηζρύεη πάληα) awk -F" " '1 {print $3"\t"$4} ' Καη αληίζηνηρν ηξόπν, ζα κπνξνύζε λα είρε παξαιεθζεί ην action, π.ρ., awk -F" " '1;1 {print $3"\t"$4} ' Κελό(Αction) Εθηύπωζε Οιόθιεξεο ηεο γξακκήο θαη κεηά ηεο ζηήιεο 3-4 Κελό(Pattern) Εθηέιεζε Action ζε θάζε γξακκή 7-12
Γνκή Πξνγξάκκαηνο awk Πην ζπγθεθξηκέλα, έλα awk πξόγξακκα απνηειείηαη από: Σν πξναηξεηηθό ηκήκα BEGIN εθηειείηαη πξηλ ηελ επεμεξγαζία ηεο πξώηεο γξακκήο εηζόδνπ. Έλα ή πεξηζζόηεξα (pattern {action}) επεμεξγαζία δεδνκέλσλ εηζόδνπ Γηα θάζε πξόηππν πνπ ηαηξηάδεη, ε αληίζηνηρε ελέξγεηα εθηειείηαη Σν πξναηξεηηθό ηκήκα END εθηειείηαη κεηά ην ηέινο επεμεξγαζίαο ηεο ηειεπηαίαο γξακκήο εηζόδνπ. [BEGIN {action;action};] pattern {action;action}; pattern {action};... pattern { action}; [END {action}] Σημείωση: (η ζειρά διαηύπφζης μπορεί να είναι ησταία) 7-13
Πξόηππα (Patterns) ζηελ awk Πξόηππν (Pattern): Πξνζδηνξηζκόο θαηά πόζνλ κηα ενέργεια-δράζη πξόθεηηαη λα εθηειεζηεί Μπνξεί λα είλαη: 1.Σν εηδηθό token BEGIN ή END $ ls awk ' > BEGIN {print "Start"; print "NOW";} > {print "LINE: "}; {print "IS:", $0} > END {print "End"}' Δπηζηξέθεη: Start NOW LINE: IS:01.pdf LINE: IS:02.pdf LINE: IS:03.pdf Action 1 BEGIN Action 2 Action 3 Action 2 Action 3 Action 2 Action 3 LINE: Action 2 IS:04.Pdf Action 3 End Action 4 END Action 1 Action 2 Action 3 Action 4 7-14
Πξόηππα (Patterns) ζηελ awk 2. Καλνληθή έθθξαζε (εζσθιεηόκελν κέζα ζε / /), όπσο κε ηελ sed, grep, κηλ. ls awk Pattern Action > 'BEGIN {print "Start..."} > /03/ {print $0} > END {print "...End"}' Δπηζηξέθεη: Start... 03.Pdf...End Pattern {Action} Δθηύπσζε γξακκήο εηζόδνπ πνπ ηθαλνπνηεί ηελ θαλνληθή έθθξαζε /03/ (πεξηέρεη ην 03) 7-15
Πξόηππα (Patterns) ζηελ awk 3. Λνγηθνί θαη ρεζηαθνί Σειεζηέο: Μνλαδηαίνο Λνγηθόο Σειεζηήο (Άξλεζεο):! Π.χ., ls awk BEGIN {print "Start..."}!/03/ {print $0} END {print "...End"}' Δθηππώλεη ηα πάληα πνπ δελ ηθαλνπνηνύλ ηελ Καλνληθή Έθθξαζε /03/ ρεζηαθνί Σειεζηέο: > < >= <= == Δπαδηθνί Λνγηθνί Σειεζηέο: && ή π.ρ. Γελ πεξηερεη ην 03 θαη είλαη κεγαιύηεξν ηνπ 10. ls awk ' > BEGIN {print "Start..."} >!/03/ && substr($0,0,2)>=10 {print $0} > END {print "...End"} ε substr είλαη ζπλάξηεζε πνπ εμάγεη από ηελ γξακκή $0 από ηελ 0 ζηήιε κέρξη ηελ 2 ζηήιε). Πεξηζζόηεξα γηα ζπλαξηήζεηο αξγόηεξα. Macro Expressions: Pattern1? Pattern2 : Pattern3 If Pattern1 ΕΠΛ is true, 371 Πξνγξακκαηηζκόο then Pattern2, πζηεκάηωλ else Pattern3 7-16
Παξαδείγκαηα Δθηέιεζεο awk Παξαδείγκαηα bash-3.1$ cat example.awk Line number 1 Line number 2 Line number 3 Line number 4 Σππώλεη ηελ γξακκή πνπ πεξηιακβάλεη ην 2 bash-3.1$ awk '/2/ {print}' example.awk Line number 2 bash-3.1$ awk '{print $3}' example.awk 1 2 Σππώλεη ηελ ηξίηε ζηήιε ηνπ αξρείνπ (ρσξίο 3 πξόηππν), ζπλεπώο γηα θάζε γξακκή. 4 7-17
Παξαδείγκαηα Δθηέιεζεο awk Παξαδείγκαηα bash-3.1$ cat example.awk Line number 1 Line number 2 To BEGIN block εθηππώλεη ην Hello you Line number 3 To main ηππώλεη ηελ γξακκή πνπ πεξηιακβάλεη ην Line number 4 2 bash-3.1$ awk '/2/ {print $0} BEGIN {print "Hello you"} END {print "goοdbye"}' example.awk Hello you Line number 2 goudbye 7-18
Παξαδείγκαηα Δθηέιεζεο awk Παξαδείγκαηα bash-3.1$ cat example2.awk Just a text file. Nothing to see here. Some lines have more fields than others and some are blank. Κελή γξακκή Δθηύπσζε ηηο γξακκέο ησλ νπνίσλ ηα πεδία είλαη > 3 bash-3.1$ awk 'NF>3 {print $0}' example2.awk Just a text file. Nothing to see here. more fields than others NF: Number of Fields 7-19
Παξαδείγκαηα Δθηέιεζεο awk Παξαδείγκαηα bash-3.1$ cat example2.awk Just a text file. Nothing to see here. Some lines have more fields than others and some are blank. Κελή γξακκή Δθηύπσζε ηηο γξακκέο ησλ νπνίσλ ηα πεδία είλαη > 3 ή είλαη θελέο bash-3.1$ awk 'NF>3 /^$/ {print $0}' example2.awk Just a text file. Nothing to see here. more fields than others Κελή γξακκή NF: Number of Fields 7-20
Παξαδείγκαηα Δθηέιεζεο awk Παξαδείγκαηα bash-3.1$ cat example2.awk Just a text file. Nothing to see here. Some lines have more fields than others and some If (NF>3) then if /file/ then print $0 Else if /^and/ then print $0 are blank. Δθηύπσζε ηηο γξακκέο ησλ νπνίσλ ηα πεδία είλαη > 3 θαη θαιύπηνπλ ην πξόηππν /file/ αιιηώο εθηύπσζε ηηο γξακκέο ησλ νπνίσλ ηα πεδία είλαη <=3 θαη μεθηλνύλ κε ην and bash-3.1$ awk 'NF>3? /file/ : /^and/ {print $0}' example2.awk Just a text file. Nothing to see here. and some 7-21
Παξαδείγκαηα Δθηέιεζεο awk Όλνκα Αξρείνπ bash-3.1$ ls -l awk > BEGIN {print "List of all.txt files"} > /\.txt$/ {print $9, $5} > END {print "There you go!!"}' Μέγεζνο αξρείνπ List of all.txt files file+1.txt 0 output.txt 4898 processes.txt 12953 test-cut.txt 55 test-sort.txt 124 test-tr.txt 40 There you go!! Δθηύπσζε ην όλνκα ηνπ αξρείνπ, πνπ έρεη πξνέθηαζε.txt θαη ην κέγεζόο ηνπ 7-22
Παξαδείγκαηα Δθηέιεζεο awk Number of Fields Παξαδείγκαηα από Actions {print NF, $1, $NF} ηππώλεη ηνλ αξηζκό ηωλ πεδίωλ, ην πξώην πεδίν, θαη ην ηειεπηαίν πεδίν ζην πθηζηάκελν record {print $(NF-2)} ηππώλεη ην ηξίην από ην ηέινο πεδίν. {print $1, $2*$3} ηππώλεη ην πξώην πεδίν θαη ην απνηέιεζκα ηνπ ππνινγηζκνύ (πνιιαπιαζηαζκόο ηνπ δεύηεξνπ θαη ηξίηνπ πεδίνπ) {print NR, $0} Πξνζζέηεη ηνλ αξηζκό ηεο πθηζηάκελεο γξακκήο πξηλ θάζε γξακκή {print total pay for, $1, is, $2*$3} πξνζζέηεηο θείκελν γηα εθηύπσζε ζηελ έμνδν καδί κε ηα πεδία ηεο πθηζηάκελεο γξακκήο Σν θείκελν εζσθιείεηαη κε Number of Records 7-23
Αξηζκεηηθέο Πξάμεηο ζηελ AWK Δλέξγεηεο Γξάζεηο Πεξηιακβάλεη ηνπο γλσζηνύο ηειεζηέο, όπσο ζηε C ++ Increment, -- Decrement ^ Exponentiation + -! Plus, Minus, NOT * / % Multiplication, division, modulus 7-24
Υξήζε πλζήθεο ζην Πξόηππν (Pattern) Επηινγή βάζε ύγθξηζεο $2 >= 5 { print } // iδιο με print $0 Επηινγή βάζε Τπνινγηζκνύ $2 * $3 > 50 { printf "%6.2f for %s\n", $2 * $3, $1) } Επηινγή βάζε Πεξηερνκέλνπ Κεηκέλνπ $1 == "NYU" $2 ~ /NYU/ => Σν $2 πεξηέρεη ην REGEX /NYU/. Πνιύ ζεκαληηθόο ηειεζηήο ζηηο θαλνληθέο εθθξάζεηο! Επηινγή βάζεη ινγηθήο έθθξαζεο $2 >= 4 $3 >= 20 7-25
Γηακόξθσζε Δμόδνπ κε ηελ printf() Καιύηεξε Γηακόξθσζε Δμόδνπ Υξήζε ηεο printf " " όπσο ζηε C awk '{ printf [(] "format", var1, var2, var3, [)]}' Παξάδεηγκα awk '{ printf " total pay for %s is $%.2f\n ", $1, $2 * $3 } Όηαλ ρξεζηκνπνηνύκε ηελ printf() ε δηακόξθσζε ηεο εμόδνπ είλαη ζηα ρέξηα καο (θελά δηαζηήκαηα, λέα γξακκή, θιπ) { printf( %-8s %6.2f\n, $1, $2 * $3 ) } Left align within 8 spaces (by default right alignment) Υαξαθηήξαο Γνιαξίνπ ζην output 6 μονάδες + 2 υηθία δεκαδικής ακρίβειας 7-26
Παξαδείγκαηα Δθηέιεζεο awk Παξαδείγκαηα bash-3.1$ ls -l awk 'BEGIN {print "List of all.txt files"} /\.txt$/ && $5>0 && NR>15 {print "line number:" NR, "file", $9, "of size:", $5} END {print "There you go!!"}' List of all.txt files line number:16 file test-cut.txt of size: 55 line number:19 file test-sort.txt of size: 124 line number:20 file test-tr.txt of size: 40 There you go!! 7-27
ή Παξαδείγκαηα Δθηέιεζεο awk Παξαδείγκαηα bash-3.1$ ls -l awk 'BEGIN {print "List of all.txt files"} /\.txt$/ && $5>0 && NR>15 && $6=="Feb" {print "line number:" NR, "file", $9, "of size:", $5} END {print "There you go!!"}' List of all.txt files line number:16 file test-cut.txt of size: 55 line number:20 file test-tr.txt of size: 40 There you go!! bash-3.1$ ls -l awk 'BEGIN {print "List of all.txt files"} /\.txt$/ && $5>0 && NR>15 && $6=="Feb" {printf("line number: %3d\tfile %15s of size %4d\n", NR, $9, $5)} END {print "There you go!!"}' List of all.txt files line number: 16 file test-cut.txt of size 55 line number: 20 file test-tr.txt of size 40 7-28
Μεηαβιεηέο ζηελ awk Μεηαβιεηέο Ζ awk κπνξεί λα νξίζεη θαη λα ρξεζηκνπνηήζεη κεηαβιεηέο $ ls awk ' > BEGIN { sum = 0 } > {sum++} > END {print sum}' Όρη απαξαίηεην Οη κεηαβιεηέο απηέο κπνξνύλ λα πάξνπλ αξηζκεηηθή (αθέξαηα ή πξαγκαηηθή) ηηκή ή ζπκβνινζεηξά ΓΔN ΓΖΛΩΝΔΣΑΗ ν ηύπνο ηνπο αιιά αλαγλσξίδεηαη από ηα ζπκθξαδόκελα. Δμ νξηζκνύ, νη κεηαβιεηέο πνπ νξίδνπκε αξρηθνπνηνύληαη κε ηελ αξηζκεηηθή ηηκή 0 ( null string) Δάλ ζέινπκε λα θάλνπκε cast έλα float ζε αθέξαηα ηηκή εθηεινύκε ηελ ζπλάξηεζε int(sum). Τπάξρνπλ ΕΠΛ δηαθνξέο 371 Πξνγξακκαηηζκόο καζ. ζπλαξ. πζηεκάηωλ (cos, log, ran, θηι), ειεμηε ην manual. 7-29
Παξαδείγκαηα Δθηέιεζεο awk Παξαδείγκαηα (Μεηαβιεηέο) awk $3 > 15 { emp = emp + 1} END { print emp, employees worked more than 15 hrs } { pay = pay + $2 * $3 } END { print NR, employees } print total pay is, pay Σππώλεη πόζνη employees δνύιεςαλ πάλσ από 15 ώξεο print average pay is, pay/nr Τπνινγίδεη ην άζξνηζκα θαη ηνλ κέζν όξν ησλ κηζζώλ πνπ ππνινγίδεηαη από ηελ 2 ε θαη 3 ε ζηήιε. 7-30
πλέλσζε πκβνινζεηξώλ ζηελ awk πλέλσζε πκβνινζεηξώλ Νέεο ζπκβνινζεηξέο κπνξνύλ λα δεκηνπξγεζνύλ κε ηε ζπλέλσζε παιηώλ { names = names $1 " " } END { print names } Παξάδεηγκα bash-3.1$ ls -l awk 'BEGIN {print "List of all.txt files"} /\.txt$/ && $5>0 && NR>15 && $6=="Feb" {names = names $9 " "; printf("line number: %3d\tfile %15s of size %4d\n", NR, $9, $5)} END {print "There you go!!"; print names}' List of all.txt files line number: 16 file test-cut.txt of size 55 line number: 20 file test-tr.txt of size 40 There you go!! test-cut.txt test-tr.txt Concat column $9 ην string, then print out line number. At the end print out name variable. string concatenation 7-31
Έιεγρνο Ρνήο Γεδνκέλσλ AWK Control Statements if (condition) then-body [else else-body] awk '{ if (x % 2 == 0) print "x is even"; else print "x is odd" } while (condition) body awk '{ i = 1 while (i <= 3) { print $i i++ } } do body while (condition) awk '{ i = 1 do { print $0 i++ } while (i <= 10) }' for (initialization; condition; increment) body awk '{ for (i = 1; i <= 3; i++) print $i } Εκηύπφζη i-οζηής ζηήλης Άιια: break, continue, exit, next (record), θηι. 7-32