【问题标题】:Strange behviour while parsing command line arguments c++解析命令行参数c ++时的奇怪行为
【发布时间】:2013-03-04 15:17:43
【问题描述】:

这是一个我以前从未见过的问题,我认为它值得分享。我不知道为什么会这样。

这就是我调用程序的方式:

./foo -switch1 arg1 -switch2 arg2 -switch3 arg3|arg4|arg5 -switch4 -arg6

每个开关用于指示不同类型的参数,我会相应地解析它们。

问题出现在switch3上,表示arg3arg4arg5都对应同一个switch,用|字符划定。

由于某种原因,我可以完美地运行该程序,但是当我尝试使用 gdb 对其进行调试时,我的程序崩溃并出现 during startup, program exited with code 127 错误。

这就是我感兴趣的地方。它还写着bin/bash: arg4 not found。它在第一个 | 字符之后使用参数,现在我假设它认为它是管道字符,并尝试调用 bash 脚本。

为什么会这样???编译器是否不采用整个命令行字符串并将空格分隔的标记视为不同的参数?为什么| 的解释不同?我尝试在倒引号"" 中添加arg3|arg4|arg5,效果很好。我还尝试通过- 将它们分开,例如。 arg3-arg4-arg5,这也很好用。

【问题讨论】:

  • “编译器不接受整个命令行字符串” - 它与编译器有什么关系?当你执行程序时,它只会接收 shell 发送给它的参数, shell 完成解析它并且管道符号对 shell 具有特殊意义。它与引号一起使用,因为这告诉 shell 不要尝试解析它。
  • 谢谢,我不知道 shell 负责将参数传递给可执行文件。我会查一下这个。

标签: c++ command-line pipe


【解决方案1】:

| 字符在bash 中具有特殊含义:它创建了一个pipeline

您的程序只看到以下参数:

./foo -switch1 arg1 -switch2 arg2 -switch3 arg3

|arg4 语法被bash 解释为应该运行(不存在的)arg4 命令,并且./foo 的标准输出应该通过管道传送到@987654329 的标准输入@。 |arg5 ... 的解释方式相同。

要抑制这种行为,请像这样运行您的程序:

./foo -switch1 arg1 -switch2 arg2 -switch3 'arg3|arg4|arg5' -switch4 -arg6

(注意引号)。

【讨论】:

  • 是的。这就是我最终想到的。反问:./foo arg1 arg2 | 之间有区别吗? some_other_executable 和 ./foo arg1|some_other_executable arg2??在这种情况下,arg2 是否被传递给 some_other_executable?
  • @SreemanananthSadanand 有一个区别,在第二个中,arg2 将被传递给另一个可执行文件,例如echo arg1 | perl -e'print "My arg1: $ARGV[0]\n" ; while(<STDIN>){ print $_; }' arg2
【解决方案2】:

问题在于| 是一个管道,因此您最终会尝试调​​用shell 找不到的arg4。您需要用管道引用其中的内容,即"arg3|arg4|arg5":

./foo -switch1 arg1 -switch2 arg2 -switch3 "arg3|arg4|arg5" -switch4 -arg6

如果您有兴趣,可以查看bash pitfalls。如果您没有进行大量的 shell 编程,您可能不会经常看到这些问题,但是当您这样做时,您可能需要一段时间才能弄清楚发生了什么,因此从长远来看,了解更多关于 shell 编程的知识可能会有所帮助。我记得我打了 3 号,第一次找到好的解决方案花了我一段时间。

【讨论】:

  • +1:是的,不是一个 shell 程序员。感谢您的链接。
  • @SreemanananthSadanand 还有其他问题或这个答案可以接受吗?
  • @ShafikYaghmour:哦,对不起,我应该提一下我的回答得到了回复。您可以关闭并存档此线程。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-21
  • 1970-01-01
  • 2013-03-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多