【发布时间】:2015-01-21 19:06:47
【问题描述】:
我正在研究 K&R C 书中的一个示例,它要求您构建一个 RPN 计算器,该计算器通过命令行参数获取输入。我的解决方案本质上是遍历给定的参数并吐出答案,但我注意到了一些事情:
如果我要给出不带单引号的乘法字符(星号)'*',gcc 会假定它是通配符输入,所以我的输入是
$./rpn 5 10 *
给我一个输出
read 5
read 10
read rpn
read rpn.c
= 0
用单引号将星号括起来可以解决问题
$./rpn 5 10 '*'
read 5
read 10
read *
= 50
我的问题是有没有办法清理输入,以便我的程序不需要用单引号括起星号,或者这种行为是由更基本的东西引起的(例如 Linux/POSIX/UNIX 二进制执行和参数处理)?
【问题讨论】:
-
全部与shell有关;与 C 编译器完全无关。为了演示,尝试编写一个小程序:
#include <unistd.h>和int main(void) { char *args[] = { "./rpn", "5", "10", "*", 0 }; execv(args[0], args); return -1; }。 shell 通常扩展*;这样可以避免使用 shell,因此不会发生扩展。 -
GCC 什么都不知道。 Shell 是向您的程序提供输入的那个。
-
@JonathanLeffler @self 我试过了,就像你说的那样;它执行并输出正确的答案。正如下面的@IgnacioVazquez-Abrar 所述,这是由 bash 将
*通配符 glob 扩展为当前目录中所有文件的列表引起的。我当然应该更加注意外壳。 -
这是一个标准的陷阱;
*是唯一常用的算术运算符,它也是一个 shell 元字符。如果您在中缀计算器中使用括号(根据定义,您不会在 RPN 计算器中使用括号),那么它们也会妨碍您,因为它们对 shell 也有特殊含义。 -
如果您真的不希望您的 Bash 不进行路径名扩展,请以
bash -f开头或在正在运行的 Bash 中键入set -f(并使用set +f撤消)。