更新的问题

更新的问题

我有一个脚本,我可以在其中动态更改必须传递给命令的参数(mkv属性编辑器在这种情况下)。考虑下面的示例脚本:

#!/bin/bash

LANG_NAME="eng lish"

MYSETTINGS=()
MYSETTINGS+=("--edit 1")
MYSETTINGS+=("--set \"language=${LANG_NAME}\"")

echo "Count = ${#MYSETTINGS[@]}" # should be 2
set -x # enable to see the invoked command
mkvpropedit ${MYSETTINGS[@]}

当我运行这个时,我进入控制台:

[~] # ./test.sh
Count = 2
+ mkvpropedit --edit 1 --set '"language=eng' 'lish"'

我想最终调用时没有单引号mkv属性编辑器,像这样:

+ mkvpropedit --edit 1 --set "language=eng lish"

我也尝试将数组回显到变量中,并且 echo 删除了单引号,但随后我无法使用该变量作为mkv属性编辑器因为单引号又出现了...

当然,如果变量是单个单词,例如LANG_NAME="eng",则脚本也必须起作用。我的 Bash 版本是 3.2(实际上是 Busybox)。

更新的问题

也许下面的例子更好地解释了我想要做的事情。我更改了一些名称以便可以复制。

#!/bin/bash

TITLE_NAME="my title"

MYSETTINGS=()
MYSETTINGS+=("--edit track:2")
MYSETTINGS+=("--set \"name=${TITLE_NAME}\"")

set -x
mkvpropedit file.mkv ${MYSETTINGS[@]} 

如果我运行这个脚本,我会得到(由于错误的引用):

# ./test.sh
+ mkvpropedit file.mkv --edit track:2 --set '"name=my' 'title"'
Error: More than one file name has been given ('file.mkv' and 'title"').

如果我手动运行:

# mkvpropedit file.mkv --edit track:2 --set "name=my title"
The file is being analyzed.
The changes are written to the file.
Done.

所以这绝对是一个引用问题;我想调用mkv属性编辑器在脚本中使用数组。

使用评估

目前看来有效的是将mkvpropeditfile.mkv插入数组并最终调用eval "${MYSETTINGS[@]}",但它值得且安全吗?不是eval 邪恶的(双关语)?

TITLE_NAME="my title"

MYSETTINGS=(mkvpropedit file.mkv)
MYSETTINGS+=("--edit track:2")
MYSETTINGS+=("--set \"name=${TITLE_NAME}\"")

set -x
eval "${MYSETTINGS[@]}"

返回:

# ./test.sh
+ eval mkvpropedit file.mkv '--edit track:2' '--set "name=my title"'
++ mkvpropedit file.mkv --edit track:2 --set 'name=my title'
The file is being analyzed.
The changes are written to the file.
Done.

答案1

没有单引号- 当您使用 时,这只是 shell 对变量内容的明确表示set -x。您可以看到,如果您使用declare -p或一次打印一个数组元素来查看数组元素:

LANG_NAME="eng lish"

MYSETTINGS=()
MYSETTINGS+=("--edit 1")
MYSETTINGS+=("--set \"language=${LANG_NAME}\"")

然后

$ declare -p MYSETTINGS
declare -a MYSETTINGS=([0]="--edit 1" [1]="--set \"language=eng lish\"")

或者

$ printf '>>>%s<<<\n' "${MYSETTINGS[@]}"
>>>--edit 1<<<
>>>--set "language=eng lish"<<<

然而,您几乎肯定希望将--edit1--set、 和language=eng lish作为单独的标记传递给命令,这意味着

  1. 在数组构造期间引用包含空格或全局字符的每个标记,例如language="${LANG_NAME}""language=${LANG_NAME}"

  2. 使用数组扩展时双引号(以防止分词和文件名生成 - 又名“split+glob”)

所以

LANG_NAME="eng lish"

MYSETTINGS=()
MYSETTINGS+=(--edit 1)
MYSETTINGS+=(--set language="${LANG_NAME}")

然后

mkvpropedit file.mkv "${MYSETTINGS[@]}"

请注意,您不需要在变量扩展周围添加额外的双引号,因为双引号"${name[@]}"会将 的每个元素扩展name为单独的单词,而无需进一步标记化 - 进一步的引号\"name=${TITLE_NAME}\"将按字面意思传递给命令。

也可以看看我们如何运行存储在变量中的命令?

答案2

[错误的] 转义美元符号:

MYSETTINGS+=("--set name=\${TITLE_NAME}")

或者:

MYSETTINGS+=('--set name=${TITLE_NAME}')
mkvpropedit file.mkv ${MYSETTINGS[@]}

用于执行命令时要扩展的变量

./test.sh
+ mkvpropedit file.mkv --edit track:2 --set 'name=${TITLE_NAME}'
The file is being analyzed.
The changes are written to the file.
Done.

相关内容