如何在执行命令之前回显命令

How to echo a command before executing it

我想在执行命令之前回显命令。此命令将字符串 'PROJECT_NAME' 替换为 file.yaml.

中的 'Hello world'
PROJECT_NAME="Hello world"
CMD="replace.py 'PROJECT_NAME' '${PROJECT_NAME}' file.yaml"
echo "${CMD}"
${CMD}

引用这个字符串的正确方法是什么,这样命令就会执行并且回显会显示命令?

注意变量 ${PROJECT_NAME} 的值包含空格,而 replace.py 恰好有 3 个参数。

我尝试转义所有引号 (\') 和美元符号 (\$)。我尝试用双引号 (") 交换单引号 (')。

通过一些引用,它会将 "Hello world" 中的每个单词视为一个单独的 arg,因此 replace.py 会因为 "world" 不是它期望的文件名而窒息。

我已阅读http://mywiki.wooledge.org/BashFAQ/050,但仍然无法理解。我不想重复命令或使用 set -x(因为在使用它时会打印 set +x 来关闭它)。

一种可能是使用数组而不是纯字符串,然后使用 printf%q 格式在需要的地方重新添加引号 and/or 转义:

PROJECT_NAME="Hello world"
CMD=(replace.py 'PROJECT_NAME' "${PROJECT_NAME}" file.yaml)
printf "%q " "${CMD[@]}"; printf "\n"
"${CMD[@]}"

请注意,这可能与您创建数组时使用的 quoting/escaping 方法不同;例如,我尝试了上面的方法并打印了:

replace.py PROJECT_NAME Hello\ world file.yaml

相当于:

replace.py 'PROJECT_NAME' "Hello world" file.yaml

...只是编写相同命令的不同方式。

存储命令行并稍后执行它的正确方法可以通过两种方式完成:

  1. 使用BASH数组
  2. 使用BASH函数

1.使用 BASH 数组:

PROJECT_NAME="Hello world"
cmd=("replace.py" "PROJECT_NAME" "$PROJECT_NAME" "file.yaml")
printf "%q " "${cmd[@]}"; echo
"${cmd[@]}"

现在 运行 为:

bash ./script.sh
replace.py PROJECT_NAME Hello\ world file.yaml

注意 printf%q 对 space 的转义。您可以直接从 shell 运行 此命令行也可以再次验证它,即

replace.py PROJECT_NAME Hello\ world file.yaml

2。使用函数:

#!/bin/bash

PROJECT_NAME="Hello world"
cmd() {
   set -x
   replace.py "PROJECT_NAME" "$PROJECT_NAME" "file.yaml"
   set +x
}

cmd

现在 运行 为:

./script.sh

你会得到类似的输出:

+ replace.py PROJECT_NAME 'Hello world' file.yaml
...
...
set +x

您还可以 运行 此命令行:

replace.py PROJECT_NAME 'Hello world' file.yaml