我正在使用这种方法打开一个 Gnome 终端窗口并运行命令——在这种情况下,向我发送简单的通知消息(将通过 安排at
):
#!/bin/sh
gnome-terminal -- /bin/sh -c 'echo "remember: $1"; exec bash'
shell 只打印remember:
字符串而不是我指定的值,例如在运行时remind.sh "pick up the package"
或remind.sh "buy groceries X and Y"
.
当我将脚本剥离到其核心时,一切都按预期工作(当然,通过 cron 或 systemd 在自动化中没有任何用处,因为前台没有显示任何内容):
#!/bin/sh
echo "remember: $1"
分析
您(或者更确切地说
gnome-terminal
,在您的情况下)提供/bin/sh -c
的代码将看到代码之后提供的位置参数。例如这个将打印
remember: first
。当代码最终被解释时,在代码导致
$1
(或$2
等$3
)扩展为空字符串之后不提供任何内容($0
有点不同,但这在这里无关紧要)。这就是你得到的原因remember:
。/bin/sh
run bygnome-terminal
对主脚本的位置参数一无所知,除非你明确地传递它们。解决方案
要使用脚本的位置参数填充内部代码的位置参数,请使用
"$@"
代替first second …
:你可以通过任何你想要的。这里我们传递所有参数(
"$@"
扩展为所有位置参数),但一般可以使用(如果您希望内部代码只"$1"
知道第一个参数)或(如果您希望内部代码看到第二个位置参数)主脚本作为自己的)。"$2"
$1
笔记
sh
因为这里解释了第零个参数:第二个 sh 是sh -c 'some shell code' sh
什么?如果在您的原始脚本(即没有我的修复)中,您打算提供的 shell 代码
sh -c
是双引号,那么解释脚本的 shell 将扩展$1
并将结果嵌入到内部代码中。不过不要这样做。在许多情况下,这会按您的预期工作;但不是一般的。一般来说,它和嵌入
{}
一样有缺陷。单引号代码和后面的参数是正确的方法。单引号代码确保它会按
/bin/sh -c
原样(内部双引号无关紧要)。然后sh
将看到代码为很好,你在这里双
$1
引号。