Ich habe eine Datei user-pid.out2
, die die beiden Spalten „Benutzernummer“ und „Prozess-ID“ hat. Basierend auf der Benutzernummer möchte ich die entsprechende Prozess-ID finden. Die ersten beiden Zeilen unten zeigen die Ausgabe nicht korrekt, aber wenn ich den Benutzer in Zeile 3 und 4 als 62 fest codiere, wird die Prozess-ID angezeigt, die dem Benutzer 62 entspricht. Kann mir bitte jemand helfen?
USR=62
usrpid=`awk '$1 == "$USR" {print $2}' /home/hu/batchhu/dbscripts_tst2/user-pid.out2`
echo "first:" $USR $usrpid
# This shows 62 and blank for process id
usrpid=`awk '$1 == "62" {print $2}' /home/hu/batchhu/dbscripts_tst2/user-pid.out2`
echo "second:" $USR $usrpid
# This shows 62 and process id corresponding to this user in the file user-pid.out2
Antwort1
@artm zeigte eine Technik, bei der Sie das awk-Skript in doppelte Anführungszeichen setzen und verschiedene Zeichen maskieren. Hier sind 3 weitere Techniken
Brechen Sie das einfache Anführungszeichen ab, damit die Shell die Variable erweitern kann.
usrpid=$(awk '$1 == "'"$USR"'" {print $2}' file)
Übergeben Sie die Shell-Variable an eine Awk-Variable
usrpid=$(awk -v usr="$USR" '$1 == usr {print $2}' file)
Wenn die Variable exportiert wird, verwenden Sie das ENVIRON-Array von awk
usrpid=$(awk '$1 == ENVIRON["USR"] {print $2}' file)
Letzteres sollte bevorzugt werden.
Im ersten Ansatz, wie bei @artm, wird der Inhalt der Shell-Variable in den awk
Code eingebettet, so dass daraus einSicherheitslücke bei der Befehlsinjektionwenn der Inhalt der Variablen nicht streng kontrolliert wird (z. B. mit USR='blah" || system("reboot") || "'
, was aufrufen würde reboot
).
Die zweite führt keine Sicherheitslücke durch Befehlsinjektion ein. Wenn sie jedoch $USR
Backslash-Zeichen enthält, usr
awk
enthält die Variable nicht dasselbe wie die $USR
Shell-Variable, da awk
dort C-ähnliche Backslash-Escape-Sequenzen erweitert werden.
Bei der Verwendung ENVIRON
treten diese Probleme nicht auf.
Antwort2
Das "$USR"
im ersten Beispiel wird nicht erweitert, weil es innerhalb der in einfache Anführungszeichen gesetzten Zeichenfolge vorkommt '$1 == "$USR" { print $2 }'
. Daher sucht dieser Code nach einer Zeile, bei der die erste Spalte „$USR“ und nicht 62 ist.
Folgendes sollte funktionieren:
usrpid=$(awk "\$1 == \"$USR\" {print \$2}" /home/hu/batchhu/dbscripts_tst2/user-pid.out2)
Änderungen:
- Die awk-Befehlszeile verwendet doppelte Anführungszeichen, daher wird $USR erweitert
- Dollarzeichen und Anführungszeichen innerhalb des Awk-Programms werden maskiert
$()
wird anstelle von Backticks verwendet, sodie Backslashes werden korrekt behandelt
Beachten Sie, dass der Wert von USR
direkt in das awk-Skript interpoliert wird und daher nur funktioniert, wenn dieser Wert nur Zeichen enthält, die von awk wörtlich interpretiert werden: Wenn oder $USR
enthält , bricht die Hölle los – wäre das Ende des awk-Zeichenfolgenliterals und würde das nächste Zeichen in Anführungszeichen setzen.\
"
"
\