环境变量未在命令行参数内展开

环境变量未在命令行参数内展开

我有一个文件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 字符串文字的结尾,并\引用下一个字符。

相关内容