【问题标题】:Shell script - proper quoting in the awk commandShell 脚本 - 在 awk 命令中正确引用
【发布时间】:2020-10-25 01:00:04
【问题描述】:

我有一个带有 2 个参数和一个条件的 awk 命令 - 如果它已满,则返回第二个参数。到目前为止,它看起来像这样并且运行良好

awk -v PARAM_NAME="user" '{ if ($1 == "\""PARAM_NAME"\":") { print $2;}}'

现在,我想添加一个检查,看看第二个参数是否以某个字符结尾。我知道,为了读取 $2 的最后一个字符,我需要这样读取它。

echo "${2: -1}"

问题是——我不知道如何正确地逃避那些双重问题(或者至少我认为问题出在哪里)。这就是我现在所拥有的,有人可以告诉我它有什么问题吗?谢谢

awk -v PARAM_NAME="user" '{ if ($1 == "\""PARAM_NAME"\":" && "${2: -1}" == "\"","\"") { print $2;}}'

整个命令

cf env some-odata-app | grep "\"hana\":" -A 30 | awk -v PARAM_NAME="user" -v lastchar="${2: -1}" '{ if ($1 == "\""PARAM_NAME"\":" && lastchar == ",") { print substr($2, 2, length($2)-3);}}'

前两个命令后的预期输入。我想从引号中清除密码和用户。所以需要知道是从末尾删掉两个还是三个字符

"hana": [
   {
    "binding_name": null,
    "credentials": {  
     "password": "obfuscated",
     "schema": "oiuhjoiuhyupoihj",
     "url": "pkpokpokp[kjpo[kpo",
     "user": "USER"
    },
 
  ]

【问题讨论】:

  • 将 shell 变量传递给 awk 应该是 awk -v var="$shell_variable" '{....}' 您能否添加更多详细信息,以便我们可以更好地理解您的问题,因为您的问题并不清楚问题。
  • 你好,这是整个命令的样子。它从 Cloud Foundry 获取环境变量并尝试清除引号,问题是 json 中的最后一个不以 coma 结尾,因此在解析它时最后一个字符会被剪切。现在只是尝试确定最后一个字符,然后需要处理这两种情况-> cf env hana-cloud-analytics-odata-app | grep "\"xsuaa\":" -A 30 | awk -v PARAM_NAME="xxx_param" '{ if ($1 == "\""PARAM_NAME"\":" && "${2: -1}" != "\"","\"") { print substr ($2, 2, 长度($2)-3);}}'
  • 如果您可以使用示例输入和所需输出(对应于示例输入)更新问题,那么理解要求会更容易一些
  • 好的,更新了 - 试图尽可能减少问题,也许这不是一个好主意:)
  • 预期的输出是什么? USERobfuscated 在不同的行上?这两个值在一行中并带有分隔符(空格?逗号?冒号?)?您需要将这 2 个值捕获到调用 shell 脚本中的变量中,还是只打印到标准输出?

标签: awk quotation-marks


【解决方案1】:

问题的要点似乎已从“将 shell 参数传递到 awk”变为“从 awk 变量/字段中提取最后一个字符”到“从 cf/grep 命令批处理中解析用户和密码”。

cf/grep 命令批处理生成的示例数据:

$ cat hana.dat
"hana": [
   {
    "binding_name": null,
    "credentials": {  
     "password": "obfuscated",
     "schema": "oiuhjoiuhyupoihj",
     "url": "pkpokpokp[kjpo[kpo",
     "user": "USER"
    },
   ]

OP 想要运行 2 个单独的命令,一个用于提取 user,另一个用于提取 password

一个使用双引号作为输入字段分隔符的awk 解决方案:

$ awk -F'"' -v PARAM_NAME="user" '$2 == PARAM_NAME { print $4 }' hana.dat
USER
$ awk -F'"' -v PARAM_NAME="password" '$2 == PARAM_NAME { print $4 }' hana.dat
obfuscated

请记住,我们也可以通过单个 awk 调用来提取这两个值,例如:

$ awk -F'"' '$2 == "password" || $2 == "user" {print $4}' hana.dat
obfuscated
USER

一个模拟awk 解决方案的grep/cut 想法:

$ grep -E 'password|user' hana.dat | cut -d'"' -f4
obfuscated
USER

注意:可能需要重新格式化输出,具体取决于 OP 计划如何捕获和使用这些值。

【讨论】:

  • 谢谢,这是完美的 - 效果很好。很抱歉造成混乱
【解决方案2】:

OP 可以添加第二个 -v 标志来拉入 shell 变量的最后一个字符,例如:

awk -v PARAM_NAME="xxx_param" -v lastchar="${2: -1}" '{ if ($1 == "\""PARAM_NAME"\":" && lastchar == "\""e"\"") { print $2;}}'

如果目标是找到输入字段的最后一个字符,我们可以使用length()substr() 函数的组合,例如,

$ awk '{ print substr($1,length($1),1) }' <<< 'STUVWXYZ'
Z

【讨论】:

  • 太棒了!在实际命令开始之前获取它是个好主意。最后一个问题 - 如果我想比较的不是字符,而是昏迷怎么办?
  • 不确定我是否理解...最后一个字符是comma?或者您是否希望比较最后一个字符以查看 it 是否为 comma
  • 我想比较最后一个字符,看是不是昏迷
  • awk -v lastchar="${2: -1}" ' .... if (lastchar == ",") ...'awk ' ... lc=substr($1,length($1),1) ; if ( lc == ",") ... '
  • 酷,出乎意料 - 不需要像“e”字符那样“逃避”昏迷
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-06
相关资源
最近更新 更多