使用bash设置参数

9

我经常运行一个简单的bash命令:

rpm -Uvh --define "_transaction_color 3" myPackage.rpm

这段代码在程序中运行良好。

但是现在我想将其编写成一个Bash文件,并使其更加灵活:

#!/bin/bash
INSTALL_CMD=rpm
INSTALL_OPT="-Uvh --define '_transaction_color 3'"

${INSTALL_CMD} ${INSTALL_OPT} myPackage.rpm

然而,这仍然会导致错误:
error: Macro % has illegal name (%define)

错误出现在处理--define和带引号的_transaction_color的方式上。
我已尝试各种转义、不同的措辞,甚至将INSTALL_OPT制成数组,并用${INSTALL_OPT[@]}进行处理。
到目前为止,我的尝试都没有成功。
显然,我想要的非常简单。只是我不确定如何实现它。
我该如何让bash正确处理我的--define参数?

你尝试过使用 INSTALL_OPT='-Uvh --define _transaction_color 3' 吗? - sampson-chen
@sampson-chen:尝试过了。“error: Macro %_transaction_color has empty body”。 - abelenky
1
这是因为bash将您的参数读取为-Uvh--define'_transaction_color3'。在这种情况下,您必须使用数组(如Barmar的答案所示):INSTALL_OPT=(-Uvh --define '_transaction_color 3')。然后${INSTALL_CMD} "${INSTALL_OPT[$@]}" myPackage.rpm可以工作(用双引号,正如他所提到的)。 - gniourf_gniourf
2个回答

14
问题在于变量替换后不会处理引号。因此,看起来你正在尝试定义一个名为'_transaction_color的宏。
尝试使用数组:
INSTALL_OPT=(-Uvh --define '_transaction_color 3')

那么:

"$INSTALL_CMD" "${INSTALL_OPT[@]}" myPackage.rpm

在IT技术中,重要的是将${INSTALL_OPT[@]}放在双引号内以获取重新引用。


1
+1 对于数组答案——这是唯一正确处理可能包含空格的多个单词的方法。 - glenn jackman
@F.Hauri 如果你认为运行不必要的进程是不好的,那么这更加邪恶。 - Barmar
@Barmar,你怎么能认为这是“不必要的”呢?虽然“邪恶”的意思是“危险的”,但eval命令会将所有内容放入当前环境中,而|sh确保离开当前环境不受影响。因此,如果有差异,有时分支可能是必要的(取决于你做什么)...但总的来说,我认为fork到sheval的安全风险相同。 - F. Hauri - Give Up GitHub
@Barmar,将${INSTALL_OPT[@]}用双引号括起来是启用重新引用还是防止变量替换时被分割成多个单词?这是一个诚实的问题,不确定单词分割的最后一句是否适用。 - nsg
1
@Nate 它执行重新引用。 这在[数组](https://www.gnu.org/software/bash/manual/html_node/Arrays.html#Arrays)中有说明:如果单词是双引号,则`${name[@]}`会将name的每个元素扩展为一个单独的单词。 - Barmar
显示剩余3条评论

-1

这可能是一个与空格分割有关的bash问题:

尝试:

#!/bin/bash

IFS=$'\n'

INSTALL_CMD=rpm
INSTALL_OPT='-Uvh'
INSTALL_OPT_DEFINE='--define _transaction_color 3'

${INSTALL_CMD} ${INSTALL_OPT} ${INSTALL_OPT_DEFINE} myPackage.rpm

我怀疑 --define 要求宏名称和值在单个参数中,因此这样做行不通。 - Barmar
@Barmar 很好的观点,我对那部分不太确定;我更新了我的答案。 - sampson-chen
@sampson-chen:尝试设置IFS并按照您描述的方式拆分选项。结果是:“-Uvh:未知选项”。(我不明白为什么...但这就是我得到的错误) - abelenky
@abelenky:尝试删除INSTALL_OPT ='-Uvh'周围的引号(或使用双引号)。另外,我在我的原始答案中错误地使用了反引号而不是单引号,以防你复制粘贴了什么。 - sampson-chen
我看到了反引号,并假设你指的是普通的引号(但我尝试了两种方式以确保)。@Barmar的答案似乎有效,感谢你的努力。 - abelenky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接