Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 如何从';(';作为用户输入,不必在整个等式周围键入转义符号或引号?_Bash_Shell_Escaping - Fatal编程技术网

Bash 如何从';(';作为用户输入,不必在整个等式周围键入转义符号或引号?

Bash 如何从';(';作为用户输入,不必在整个等式周围键入转义符号或引号?,bash,shell,escaping,Bash,Shell,Escaping,我用C语言编写了一个简单的计算器,它使用递归下降解析器。这一切都很好用,但当我以“(”符号开始时出现了一个问题 我从argv[1]获取用户输入,并将内容放入一个全局变量中以暂时简化。然后,我只需遍历字符串中的每个字符,并查找它可能是什么模式,例如数字、加号或乘法(就像一个常规的递归下降解析器工作一样,没有真正的花哨工作) 但是,如果我这样做: ./calculator (1+2)*0.5 我收到一条错误消息 bash:意外标记“1+2”附近出现语法错误 这是因为我必须避开“(”和“)”所以 很

我用C语言编写了一个简单的计算器,它使用递归下降解析器。这一切都很好用,但当我以“(”符号开始时出现了一个问题

我从argv[1]获取用户输入,并将内容放入一个全局变量中以暂时简化。然后,我只需遍历字符串中的每个字符,并查找它可能是什么模式,例如数字、加号或乘法(就像一个常规的递归下降解析器工作一样,没有真正的花哨工作)

但是,如果我这样做:

./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)