Umgebungsvariable nicht innerhalb des Befehlszeilenarguments erweitert

Umgebungsvariable nicht innerhalb des Befehlszeilenarguments erweitert

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 awkCode 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 $USRBackslash-Zeichen enthält, usr awkenthält die Variable nicht dasselbe wie die $USRShell-Variable, da awkdort C-ähnliche Backslash-Escape-Sequenzen erweitert werden.

Bei der Verwendung ENVIRONtreten 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:

  1. Die awk-Befehlszeile verwendet doppelte Anführungszeichen, daher wird $USR erweitert
  2. Dollarzeichen und Anführungszeichen innerhalb des Awk-Programms werden maskiert
  3. $()wird anstelle von Backticks verwendet, sodie Backslashes werden korrekt behandelt

Beachten Sie, dass der Wert von USRdirekt 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 $USRenthält , bricht die Hölle los –  wäre das Ende des awk-Zeichenfolgenliterals und würde das nächste Zeichen in Anführungszeichen setzen.\""\

verwandte Informationen