【问题标题】:Echo command + variable expansion before exec执行前回显命令+变量扩展
【发布时间】:2015-10-30 05:02:47
【问题描述】:

如何在执行前回显实际命令 WITH 扩展变量(由它们的值替换)? SO中有类似的问题,其中大多数答案建议使用set -x或set -v。不知何故,这在我的情况下不起作用。希望您能帮助查明错误:

myTest.sh的内容

#!/bin/sh
set -v # enable echo command before execution

myTable="TEST_COL890_TABLE"
WhereClause="coL2 > 0"

grep -Eio Col[0-9]+ <<- EOF
  SELECT * FROM $myTable
  GROUP BY Col1
  WHERE $WhereClause
  ORDER BY Col3
EOF

set +v # disable echo command before execution

执行者:

$ chmod 744 ./myTest.sh
$ sh ./myTest.sh

控制台输出(注意变量未展开)

myTable=TEST_COL890_TABLE
+ myTable=TEST_COL890_TABLE
WhereClause="coL2 > 0"
+ WhereClause='coL2 > 0'

grep -Eio Col[0-9]+ 选择 * 从 $myTable
按 Col1 分组
WHERE $WhereClause
由 Col3 订购
EOF
+ grep -Eio 'Col[0-9]+'
COL890
Col1
coL2
Col3

set +vx # 在执行前禁用 echo 命令
+ 设置 +vx

预期的屏幕输出(变量 $myTable 和 $WhereClause 被它们的值替换)

myTable=TEST_COL890_TABLE
WhereClause="coL2 > 0"

grep -Eio Col[0-9]+ SELECT * FROM TEST_COL890_TABLE
按 Col1 分组
哪里 coL2 > 0
由 Col3 订购
EOF
+ grep -Eio 'Col[0-9]+'
COL890
Col1
coL2
Col3

【问题讨论】:

  • 它不起作用,因为它不是实际命令的一部分,它是重定向的一部分,命令只是grep -Eio Col[0-9]+。尝试将值分配给变量,然后再将其输入grep,它可能会以这种方式显示扩展。
  • @Polymerase:请注意,你的 shebang 行是 #!/bin/sh,但如果你真的在谈论 Bash,它应该是 #!/bin/bash(或 #!/usr/bin/env bash )
  • @mklement0 我的开发环境是 bash。但是该脚本将在带有 Korn shell 的 Redhat 6.4 上运行。如果我听从你的建议,那还可以吗?
  • @Polymerase:只要在您的目标机器上安装了 Bash,您就应该使用 Bash shebang 行——它可以让您自信地使用 Bash 功能而不必担心交叉-外壳兼容性。
  • 我同意 mklement0,针对编写代码的特定 shell 更好。

标签: linux bash


【解决方案1】:

set -v 上的 Bash 文档:

在读取 shell 输入行时打印它们。

(前面的意思是不做扩展)。

set -x 上的 Bash 文档:

打印简单命令的痕迹,对于命令,case命令,select 命令,以及命令及其参数的算术或 相关单词列表在它们展开之后和之前 执行。 PS4 变量的值被展开,结果 value 在命令及其扩展参数之前打印。

我猜set -x 不显示重定向数据,您只看到set -v 输出的未扩展读取行。

如果您将在 EOF heredoc 中使用的文本分配给一个变量,set -x 将在执行分配时正确地显示扩展值。

所以,把你的代码改成这样:

select="SELECT * FROM $myTable
GROUP BY Col1
WHERE $WhereClause
ORDER BY Col3"

grep -Eio 'Col[0-9]+' <<< "$select"

【讨论】:

  • @mklement0 我通常只记住不要碰撞流行的环境变量,但我想不使用全大写名称会更好,这似乎是一个好习惯:P
【解决方案2】:

补充 KurzedMetal's helpful answer:

如果您仍然需要此处文档的灵活性(不必引用嵌入的双引号,可以选择去除前导标签),请尝试以下操作:

# Read input into variable $input via here-document
IFS= read -r -d '' input <<-EOF
  SELECT * FROM $myTable
  GROUP BY Col1
  WHERE $WhereClause
  ORDER BY Col3
EOF

# Turn on tracing
set -x

# Use `:`, a special builtin called the null utility whose sole purpose is
# to expand its arguments - and nothing else.
# With -x on, this will print the expanded value.
# If -x is off, expansions still occur, but without any visible or side effects.
: "$input"

# Invoke the command - input provided via stdin (<<<) will NOT show.
grep -Eio 'Col[0-9]+' <<< "$input"

# Turn tracing back off
set +x

另请参阅:POSIX spec for :,null 实用程序。

【讨论】:

  • 太棒了,我更喜欢这个解决方案。在此过程中了解了“null 实用程序”。
猜你喜欢
  • 1970-01-01
  • 2021-11-18
  • 2014-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-29
  • 2011-10-17
相关资源
最近更新 更多