Θα αναφερόμαστε στη γλώσσα ως AWK και στο εκτελέσιμο που ερμηνεύει προγράμματα AWK ως awk ή gawk.
Ένα πρόγραμμα AWK αποτελείται από ζεύγη μοτίβου-ενέργειας
pattern1 { action1 }
pattern2 { action2 }
...
Ένα μοτίβο μπορεί να είναι ένα μοτίβο κανονικής έκφρασης για αντιστοίχιση με την είσοδο. Μπορεί επίσης να είναι οποιαδήποτε έκφραση που έχει ως αποτέλεσμα μια τιμή αληθής/ψευδής.
Μια ενέργεια είναι μία ή περισσότερες εντολές AWK. Τα άγκιστρα που την περικλείουν είναι υποχρεωτικά.
Αν το αποτέλεσμα του μοτίβου είναι αληθής, τότε εκτελείται η αντίστοιχη ενέργεια.
Το AWK αναλύει την είσοδο ως μια σειρά από καταγραφές. Κάθε καταγραφή χωρίζεται σε μηδέν ή περισσότερα πεδία.
Η προεπιλεγμένη συμπεριφορά είναι η εξής:
Το μοτίβο μπορεί να παραλειφθεί, οπότε η ενέργεια εκτελείται για κάθε καταγραφή εισόδου.
Η ενέργεια μπορεί να παραλειφθεί, οπότε η προεπιλεγμένη ενέργεια είναι να εκτυπωθεί η τρέχουσα καταγραφή.
Υπάρχουν δύο ειδικά μοτίβα που χρησιμοποιούνται συχνά.
BEGIN εκτελεί τη σχετική ενέργεια πριν καταναλωθεί οποιαδήποτε είσοδος.END εκτελεί τη σχετική ενέργεια αφού καταναλωθεί όλη η είσοδος.Αναφέρεσαι στα πεδία ως $1, $2, $3, κ.λπ.
Η τρέχουσα καταγραφή είναι $0.
Για να είμαστε σαφείς, αυτά δεν είναι αυστηρά "μεταβλητές".
Το $ μπορεί να θεωρηθεί ως ένας τελεστής που παίρνει την τιμή του δεδομένου αριθμού πεδίου.
Θα εμβαθύνουμε σε αυτό σε επόμενες έννοιες.
Ακολουθούν μερικές άλλες συχνά χρησιμοποιούμενες ενσωματωμένες μεταβλητές.
RS είναι το διαχωριστικό καταγραφών εισόδου.
Όπως αναφέρθηκε, η προεπιλεγμένη τιμή του είναι η νέα γραμμή.FS είναι το διαχωριστικό πεδίων εισόδου.Αυτές οι μεταβλητές συχνά ορίζονται στο μπλοκ ενέργειας BEGIN.
Αυτές οι μεταβλητές ορίζονται αυτόματα από το AWK κατά την εκτέλεση του προγράμματος.
NF αποθηκεύει τον αριθμό των πεδίων στην τρέχουσα καταγραφή.
$NF.NR αποθηκεύει τον τρέχοντα αριθμό καταγραφής.
NR θα περιέχει τον συνολικό αριθμό καταγραφών που έχουν υποστεί επεξεργασία μέχρι στιγμής.FNR αποθηκεύει τον τρέχοντα αριθμό καταγραφής του τρέχοντος αρχείου εισόδου.
NR == FNR {action}
Αυτό σημαίνει "αν ο συσσωρευμένος αριθμός καταγραφών ισούται με τον αριθμό καταγραφής του τρέχοντος αρχείου".
Αυτό μπορεί να ισχύει μόνο για καταγραφές στο πρώτο αρχείο εισόδου.Το AWK χρησιμοποιεί την ίδια έννοια αληθότητας όπως η C:
0 είναι ψευδής.Επειδή το AWK είναι μια γλώσσα επεξεργασίας κειμένου, οι τιμές αληθείας επεκτείνονται και στις συμβολοσειρές.
"" είναι ψευδής.Το AWK χρησιμοποιεί την ίδια έννοια αληθότητας όπως η C
Το AWK δημιουργήθηκε στα Bell Labs τη δεκαετία του 1970, στο ίδιο περιβάλλον όπου εφευρέθηκε η C. Η C άσκησε μεγάλη επιρροή στη σύνταξη του AWK.
Μια παραξενιά που πρέπει να προσέξεις
0 είναι ψευδής."0" είναι αληθής!Θα ασχοληθούμε περισσότερο με τους τύπους δεδομένων του AWK σε επόμενες έννοιες.
Τα σχόλια ξεκινούν με τον χαρακτήρα # και εκτείνονται μέχρι το τέλος της γραμμής.
awk
Το awk μπορεί να διαβάσει είσοδο από αρχεία ή από την τυπική είσοδο.
Οποιαδήποτε από αυτές τις τεχνικές θα λειτουργήσει.
awk '/regex/ {print $1}' file1 file2 ...
awk '/regex/ {print $1}' < file
some_command_here | awk '/regex/ {print $1}'
Σε συστήματα που μοιάζουν με Unix, το /etc/passwd περιέχει πληροφορίες για τους χρήστες.
Κάθε χρήστης περιγράφεται σε ξεχωριστή γραμμή, με τα πεδία να χωρίζονται με άνω και κάτω τελείες.
Για να εμφανίσεις τα ονόματα χρηστών:
awk '
BEGIN { FS = ":" }
{ print $1 }
' /etc/passwd
Πρόσεξε ότι η ενέργεια {print $1} δεν έχει μοτίβο, οπότε εκτελείται για κάθε καταγραφή.
Αν θέλουμε να περιορίσουμε την έξοδο μόνο στους χρήστες που χρησιμοποιούν το bash ως φλοιό σύνδεσης, μπορούμε να κάνουμε το εξής:
awk '
BEGIN { FS = ":" }
$7 == "/bin/bash" { print $1 }
' /etc/passwd
Ακολουθούν μερικά προγράμματα awk που παράγουν τα ίδια αποτελέσματα με άλλες κοινές εντολές του Unix.
Εμφάνιση ενός αρχείου
cat file.txt
awk '1' file.txt
Αναζήτηση μοτίβων σε ένα αρχείο
grep 'foo.*bar' file.txt
awk '/foo.*bar/' file.txt
Εμφάνιση μόνο μερικών γραμμών στην αρχή ενός αρχείου
head -n 20 file.txt
awk '
1
NR == 20 {exit}
' file.txt
Αντικατάσταση κειμένου σε ένα αρχείο
sed 's/foo/bar/' file.txt
awk '{sub(/foo/, "bar")};1' file.txt
# or more readably
awk '
{
sub(/foo/, "bar")
print
}
' file.txt