Bash 如何从';(';作为用户输入,不必在整个等式周围键入转义符号或引号?
我用C语言编写了一个简单的计算器,它使用递归下降解析器。这一切都很好用,但当我以“(”符号开始时出现了一个问题 我从argv[1]获取用户输入,并将内容放入一个全局变量中以暂时简化。然后,我只需遍历字符串中的每个字符,并查找它可能是什么模式,例如数字、加号或乘法(就像一个常规的递归下降解析器工作一样,没有真正的花哨工作) 但是,如果我这样做:Bash 如何从';(';作为用户输入,不必在整个等式周围键入转义符号或引号?,bash,shell,escaping,Bash,Shell,Escaping,我用C语言编写了一个简单的计算器,它使用递归下降解析器。这一切都很好用,但当我以“(”符号开始时出现了一个问题 我从argv[1]获取用户输入,并将内容放入一个全局变量中以暂时简化。然后,我只需遍历字符串中的每个字符,并查找它可能是什么模式,例如数字、加号或乘法(就像一个常规的递归下降解析器工作一样,没有真正的花哨工作) 但是,如果我这样做: ./calculator (1+2)*0.5 我收到一条错误消息 bash:意外标记“1+2”附近出现语法错误 这是因为我必须避开“(”和“)”所以 很
./calculator (1+2)*0.5
我收到一条错误消息
bash:意外标记“1+2”附近出现语法错误
这是因为我必须避开“(”和“)”所以
很好
所以我的问题是:
我如何解决这个问题,而不必考虑eater在等式周围加上单引号或双引号,或者逃避它们
为什么0.5*(1+2)仍在工作?我是否也必须转义括号?这里发生的事情是,您的行看起来像一个函数定义:
$ ./calculator () {
> echo "function called with arguments '$@'"
> }
func () { echo "$@"; }
定义一个名为/calculator
的shell函数。然后可以像执行命令一样调用它:
$ ./calculator arguments go here
function called with arguments 'arguments go here'
您的错误源于这样一个事实:Bash希望(
后面跟着)
使其成为一个正确的函数定义,但您的父母并不是空的
Bash shell在命令行中保留许多元字符,而不仅仅是括号。*
用于生成路径名。不同的shell工作方式不同;在Z shell(zsh)中,即使这样也不起作用:
% ./calculator 1*2
zsh: no match
当在命令行中给出这些元字符时,您应该必须转义所有这些元字符。不要学习“安全子集”,因为很快您将尝试另一个shell,但它失败。或者可能发生这种情况:
$ echo 1*2
1*2
$ touch 1-31337-2
$ echo 1*2
1-31337-2
有两种简单的解决方案可以避免反斜杠:
$ ./calculator '(1+2)*0.5'
如果字符串不包含“
,则可以很好地工作
双引号也可以使用,但也有,例如$
$ ./calculator
calculator> 1 + 2 * 0.5
例如,您也可以使用readline
库进行简单的交互式编辑这里发生的情况是,您的行看起来像一个函数定义:
$ ./calculator () {
> echo "function called with arguments '$@'"
> }
func () { echo "$@"; }
定义一个名为/calculator
的shell函数。然后可以像执行命令一样调用它:
$ ./calculator arguments go here
function called with arguments 'arguments go here'
您的错误源于这样一个事实:Bash希望(
后面跟着)
使其成为一个正确的函数定义,但您的父母并不是空的
Bash shell在命令行中保留许多元字符,而不仅仅是括号。*
用于生成路径名。不同的shell工作方式不同;在Z shell(zsh)中,即使这样也不起作用:
% ./calculator 1*2
zsh: no match
当在命令行中给出这些元字符时,您应该必须转义所有这些元字符。不要学习“安全子集”,因为很快您将尝试另一个shell,但它失败。或者可能发生这种情况:
$ echo 1*2
1*2
$ touch 1-31337-2
$ echo 1*2
1-31337-2
有两种简单的解决方案可以避免反斜杠:
$ ./calculator '(1+2)*0.5'
如果字符串不包含“
,则可以很好地工作
双引号也可以使用,但也有,例如$
$ ./calculator
calculator> 1 + 2 * 0.5
例如,您也可以使用readline
库进行简单的交互式编辑小结:引用您的表达式(最好使用单引号)或使用除
(
和)
以外的内容进行分组
有关“为什么0.5*(1+2)
有效?”的答案,请转到结尾。(提示:这是因为您没有名为0.5
的文件)
括号是bash手册所指的符号。(Posix不再使用这个术语,而是将这些字符称为“运算符”。但基本效果是一样的。)除非加引号,否则元字符本身始终是标记(或者,在类似
的情况下:引用表达式(最好用单引号)或者使用非(
和)
的方法进行分组
有关“为什么0.5*(1+2)
有效?”的答案,请转到结尾。(提示:这是因为您没有名为0.5
的文件)
括号是bash手册中提到的(Posix不再使用这个术语,而是将这些字符称为“操作符”。但基本效果是一样的。)除非被引用,元字符本身总是标记(或者,在类似的情况下,这似乎是一个shell问题,而不是C问题。添加了标记。是的,我使用的是bash,您认为我应该搜索什么来找出问题?很好。我只是添加了一个标记,以便bash专家能够找到它并给出更好的答案。@Salviati:您需要意识到的基本点是,无论您在命令上键入什么,都可以和行必须是有效的shell语法。您的脚本无法更改该语法。shell根据其规则解析命令行,然后(如果工作正常)将结果传递给脚本。/calculator(1+2)*0.5
不是有效的shell语法,您的脚本无法更改。感谢您的解释!我现在理解了这一点,我提出这个问题的原因是为了避免将来出现这种情况,我只知道它是如何构建的。它没有错,我只是想理解。谢谢!这似乎是shell问题,而不是C问题e、 添加了标记。是的,我正在使用bash,您认为我应该搜索什么来找出问题?很好。我只是添加了一个标记,以便bash专家能够找到它并给出更好的答案。@Salviati:您需要意识到的一点是,无论您在命令行上键入什么,都必须是有效的shell语法。您的脚本无法更改它。The shell根据其规则解析命令行,然后(如果可以的话)
$ echo a+(b+4)
a+(b+4)
$ echo a-(b+4)
bash: syntax error near unexpected token `('
$ echo a*(b+4)
a*(b+4)
$ echo a/(b+4)
bash: syntax error near unexpected token `('
?(pattern-list)
Matches zero or one occurrence of the given patterns
*(pattern-list)
Matches zero or more occurrences of the given patterns
+(pattern-list)
Matches one or more occurrences of the given patterns
@(pattern-list)
Matches one of the given patterns
!(pattern-list)
Matches anything except one of the given patterns
$ touch ab+4b+4b+4
$ echo a+(b+4)
ab+4b+4b+4
$ rm ab+4b+4b+4
$ echo a+(b+4)
a+(b+4)
$ shopt -s failglob
$ echo a+(b+4)
bash: no match: a+(b+4)