環境變數未在命令列參數內擴展

環境變數未在命令列參數內擴展

我有一個文件user-pid.out2,其中有“用戶號”和“進程 ID”作為兩列。根據usernumber我想找對應的進程id。下面的前兩行沒有顯示正確的輸出,但是當我在第 3 行和第 4 行中將用戶硬編碼為 62 時,它顯示了與用戶 62 相對應的進程 ID。

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

答案1

@artm 展示了一種雙引號 awk 腳本並轉義各種字符的技術。這裡還有另外 3 種技巧

跳出單引號讓shell擴展變數

usrpid=$(awk '$1 == "'"$USR"'" {print $2}' file)

將 shell 變數傳遞給 awk 變數

usrpid=$(awk -v usr="$USR" '$1 == usr {print $2}' file)

如果變數是導出的,則使用awk的ENVIRON數組

usrpid=$(awk '$1 == ENVIRON["USR"] {print $2}' file)

後者應該是首選。

在第一種方法中,就像 @artm 的方法一樣,shell 變數的內容嵌入到程式碼中awk,這樣就變成了命令注入漏洞如果變數的內容沒有受到嚴格控制(例如, with USR='blah" || system("reboot") || "',則會呼叫reboot)。

第二個不會引入命令注入漏洞,但如果$USR包含反斜線字符,則該變數將不會包含與shell 變數usr awk相同的內容,因為其中會擴展類似 C 的反斜線轉義序列。$USRawk

使用ENVIRON就沒有這些問題。

答案2

第一個範例中的the"$USR"未展開,因為它出現在單引號字串內'$1 == "$USR" { print $2 }',因此此程式碼正在尋找第一列為「$USR」而不是 62 的行。

以下應該有效:

usrpid=$(awk "\$1 == \"$USR\" {print \$2}" /home/hu/batchhu/dbscripts_tst2/user-pid.out2)

變化:

  1. awk 命令列使用雙引號,因此 $USR 被擴展
  2. awk 程式中的美元符號和引號字元被轉義
  3. $()使用而不是反引號所以反斜線處理正確

請注意,由於 的值USR是直接插值到 awk 腳本中的,因此只有當該值僅包含 awk 將按字面解釋的字符時它才有效:如果$USR包含\",則一切都會崩潰 - "將是awk 字符串文字的結尾,並\引用下一個字元。

相關內容