我编写了一个小程序,它从
*argv[]
获取一些输入参数并打印它们。在几乎所有用例中,我的代码都运行得很好。仅当我在要作为参数传递的字符串末尾使用多个感叹号时,才会出现问题...
这有效:
./program -m "Hello, world!"
这不起作用:
./program -m "Hello, world!!!!"
^^ 如果我这样做,程序输出要么是该字符串的两倍,要么是我在 ./program 之前输入的命令。
但是,我绝对不明白:奇怪的是,以下内容确实有效:
./program -m 'Hello, world!!!!'
^^ 输出正是...
Hello, world!!!!
...正如所愿。
所以,我的问题是:
""
表示字符串,使用 ''
表示单个字符。那么为什么我在使用 ''
时得到了想要的结果,但在使用 ""
时却没有得到预期的结果(以我的理解)?我的代码的相关部分:
// this is a simplified example that, in essence, does the same
// as my (significantly longer) code
int main(int argc, char* argv[]) {
char *msg = (char *)calloc(1024, sizeof(char));
printf("%s", strcat(msg, argv[2])); // argv[1] is "-m"
free(msg);
}
我已经尝试先将
argv[2]
的内容复制到 char*
缓冲区中,然后在其中附加 '\0'
,这没有改变任何内容。
这与您的代码无关,而是与启动它的 shell 相关。
在大多数 shell 中,
!!
是最后运行的命令的简写。当您使用双引号时,shell 允许在字符串中进行历史扩展(以及变量替换等),因此当您将!!
放入双引号字符串内时,它会替换最后运行的命令。
这对您的程序意味着所有这些都发生在您的程序执行之前,因此除了检查传入的字符串是否有效之外,程序无能为力。
相反,当您使用单引号时,shell不会进行任何替换,并且字符串会不经修改地传递给程序。
所以需要使用单引号来传递这个字符串。如果您的用户不希望发生任何替换,他们需要知道这一点。另一种方法是创建一个包装 shell 脚本,提示用户输入要传入的字符串,然后该脚本随后将使用正确的参数调用您的程序。
Bash 手册页(假设您使用 Bash,这是大多数 Linux 发行版的默认设置),那么如果您查看 历史扩展部分,您将看到 !!
的意思是
请参阅上一条命令。因此,双引号字符串中的
!!!!
将扩展为上一个命令,两次。这种扩展不适用于单引号字符串。
所以问题不在你的程序内部,而是由于调用你的程序的环境(shell)造成的。
echo ./program -m "Hello, world!!!!"
这会给你带来一些奇怪的感觉,并可能帮助你走向正确的方向。