Πώς μπορώ να χρησιμοποιήσω μεταβλητές κελύφους σε ένα σενάριο awk;

Βρήκα μερικούς τρόπους για να περάσω εξωτερικές μεταβλητές κελύφους σε ένα σενάριο awk, αλλά είμαι μπερδεμένος σχετικά με τα ' και ".

Αρχικά, δοκίμασα με ένα σενάριο κελύφους:

$ v=123test
$ echo $v
123test
$ echo "$v"
123test

Στη συνέχεια δοκίμασα awk:

$ awk 'BEGIN{print "'$v'"}'
$ 123test
$ awk 'BEGIN{print '"$v"'}'
$ 123

Γιατί είναι η διαφορά;

Τέλος, δοκίμασα αυτό:

$ awk 'BEGIN{print " '$v' "}'
$  123test
$ awk 'BEGIN{print ' "$v" '}'
awk: cmd. line:1: BEGIN{print
awk: cmd. line:1:             ^ unexpected newline or end of string 

Έχω μπερδευτεί με αυτό.

Λύση

Παίρνοντας μεταβλητές του κελύφους στο awk

μπορεί να γίνει με διάφορους τρόπους. Μερικοί είναι καλύτεροι από άλλους. Αυτό θα πρέπει να καλύπτει τους περισσότερους από αυτούς. Αν έχετε κάποιο σχόλιο, αφήστε το παρακάτω.


Χρησιμοποιώντας το -v (Ο καλύτερος τρόπος, ο πιο φορητός)

Χρησιμοποιήστε την επιλογή -v: (Υ.Γ. χρησιμοποιήστε ένα κενό μετά το -v αλλιώς θα είναι λιγότερο φορητό. Π.χ., awk -v var= όχι awk -vvar=)

variable="line one\nline two"
awk -v var="$variable" 'BEGIN {print var}'
line one
line two

Αυτό θα πρέπει να είναι συμβατό με τα περισσότερα awk, και η μεταβλητή είναι διαθέσιμη και στο μπλοκ BEGIN:

Εάν έχετε πολλαπλές μεταβλητές:

awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'

Προειδοποίηση. Όπως γράφει ο Ed Morton, οι ακολουθίες διαφυγής θα ερμηνευτούν έτσι ώστε το \t να γίνει πραγματική tab και όχι \t αν αυτό είναι που ψάχνετε. Μπορεί να λυθεί με τη χρήση του ENVIRON[] ή με πρόσβαση μέσω του ARGV[].

PS Αν σας αρέσουν οι τρεις κάθετες γραμμές ως διαχωριστικό ||||, δεν μπορούν να διαφυγούν, οπότε χρησιμοποιήστε -F"[|][|][|][|]"

Παράδειγμα λήψης δεδομένων από ένα πρόγραμμα/μια λειτουργία inn to awk (εδώ χρησιμοποιείται η ημερομηνία)

awk -v time="$(date +"%F %H:%M" -d '-1 minute')" 'BEGIN {print time}'

Μεταβλητή μετά το μπλοκ κώδικα

Εδώ παίρνουμε τη μεταβλητή μετά τον κώδικα awk. Αυτό θα λειτουργήσει μια χαρά εφόσον δεν χρειάζεστε τη μεταβλητή στο μπλοκ BEGIN:

variable="line one\nline two"
echo "input data" | awk '{print var}' var="${variable}"
or
awk '{print var}' var="${variable}" file

Αυτό λειτουργεί επίσης με πολλαπλές μεταβλητές awk '{print a,b,$0}' a="$var1&quot- b="$var2&quot- file

Η χρήση μεταβλητής με αυτόν τον τρόπο δεν λειτουργεί στο μπλοκ BEGIN:

echo "input data" | awk 'BEGIN {print var}' var="${variable}"

Here-string

Η μεταβλητή μπορεί επίσης να προστεθεί στο awk χρησιμοποιώντας ένα [here-string][1] από τα κελύφη που τα υποστηρίζουν (συμπεριλαμβανομένου του Bash):


awk '{print $0}' 
Σχόλια (6)

Χρησιμοποιήστε οποιαδήποτε από αυτές ανάλογα με το πώς θέλετε να χειρίζεστε τις backslashes στις μεταβλητές του κελύφους (avar είναι μια μεταβλητή awk, svar είναι μια μεταβλητή του κελύφους):

awk -v avar="$svar" '... avar ...' file
awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file

Δείτε το http://cfajohnson.com/shell/cus-faq-2.html#Q24 για λεπτομέρειες και άλλες επιλογές. Η πρώτη παραπάνω μέθοδος είναι σχεδόν πάντα η καλύτερη επιλογή σας και έχει την πιο προφανή σημασιολογία.

Σχόλια (0)

Θα μπορούσατε να περάσετε την επιλογή γραμμής εντολών -v με ένα όνομα μεταβλητής (v) και μια τιμή (=) της μεταβλητής περιβάλλοντος ("${v}"):

% awk -vv="${v}" 'BEGIN { print v }'
123test

Ή για να το κάνουμε πιο σαφές (με πολύ λιγότερα v):

% environment_variable=123test
% awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
123test
Σχόλια (0)