我编写了一个小程序,它从*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'
,但这并没有改变任何内容。
答案 0 :(得分:68)
这与你的代码无关,而是与启动它的shell有关。
在大多数shell中,!!
是最后一个运行命令的简写。当你使用双引号时,shell允许在字符串中使用history expansion(以及变量替换等),所以当你将!!
放在双引号字符串中时,它会替换最后一个命令运行。
这对你的程序来说意味着所有这一切都发生在之前你的程序执行,所以除了检查传入的字符串是否有效之外,程序不能做什么。
相反,当你使用单引号时,shell会不进行任何替换,并且字符串将被未经修改地传递给程序。
因此您需要使用单引号来传递此字符串。如果用户不希望发生任何替换,他们需要知道这一点。另一种方法是创建一个包装器shell脚本,提示用户输入字符串,然后脚本将使用正确的参数调用您的程序。
答案 1 :(得分:9)
shell在双引号字符串中进行扩展。如果您阅读the Bash manual page(假设您使用Bash,这是大多数Linux发行版的默认设置),那么如果您查看the History Expansion section,您会看到!!
表示
请参阅上一个命令。
因此,双引号字符串中的!!!!
将扩展为上一个命令,两次。
这种扩展不适用于单引号字符串。
所以问题不在你的程序中,这是由于环境(shell)调用你的程序。
答案 2 :(得分:8)
除了提供的答案之外,你应该记住echo是你的shell好友。如果您在命令前加上" echo",您将看到实际发送到您的脚本的shell。
echo ./program -m "Hello, world!!!!"
这会让你有些陌生,可能会帮助你引导你走向正确的方向。