bash在名为“@”的函数上的奇怪行为

时间:2017-03-30 12:19:58

标签: bash

今天我在bash中发现了一个奇怪的行为。

使用以下语法在交互式shell中定义名为“@”的函数时:

$ function @() { echo foo; }

它(当然)定义了一个名为“@”的函数。

但是,在特定情况下,例如在tmux会话或虚拟控制台中( Ctrl + Alt + F1 ),这定义了一个名为“@()”的函数。 我在这些环境中找不到任何差异(echo $-的输出为himBH)。此外,function @ { echo bar; }没有此陷阱,并在两种情况下定义“@”。我找不到任何文件说@是bash中的特殊符号。

有人对此有所了解吗? 我在香草Ubuntu 16.04.2上证实了这些。

2 个答案:

答案 0 :(得分:4)

“问题”是由shell选项extglob引起的。

extglob:on

[STEP 100] # echo $BASH_VERSION
4.4.12(1)-release
[STEP 101] # shopt -s extglob 
[STEP 102] # echo @()
@()
[STEP 103] # function @() { shopt extglob; }
[STEP 104] # @()
extglob         on
[STEP 105] # unset -f @()
[STEP 106] # 

extglob on时,我猜Bash的语法分析器会将@()视为一个整体(因为它看起来像一个有效的扩展的glob模式)并将其传递给{{ 1}}命令为一个参数,因此function采用function @() {}语法,因此function NAME {}是函数名称。

extglob:off

@()

[STEP 107] # shopt -u extglob [STEP 108] # echo @() bash: syntax error near unexpected token `(' [STEP 109] # function @() { shopt extglob; } [STEP 110] # @ extglob off [STEP 111] # 时,extglob off采用function @() {}语法,因此function NAME() {}是函数名称。

bug-bash 邮件列表中的切特explanation

  

shell函数名称是WORD,但POSIX模式将其限制为NAME。   它没有经历任何扩展。

     

启用@时,extglob是WORD的一部分,因为它是有效的扩展   glob模式和glob模式可以包含在WORD中。这是一   启用@()时,不同解析器行为的示例。所以   定义名为extglob的函数没有问题。当@()时   如果未启用,则extglob不是有效模式,并且将parens解析为   单独的运营商在这种情况下,它们恰好有意义,并定义了一个   名为@()的函数。

     

当你尝试执行它时,由于它没有被引用,它会经历正常状态   单词扩展,其中之一是文件名生成。它不匹配   任何东西,所以它保持不变,名为@的函数执行。什么时候   @()已启用,模式仍然与任何内容都不匹配,而且是   除去。这将为您提供null命令,该命令也会执行,和   返回状态0。

答案 1 :(得分:1)

在bash中有两种情况(我都知道)" @"使用符号。第一个是处理参数时:

function mytest() {
    echo $@
}
mytest "param1" "param2" "param3"

第二个是处理数组时:

declare myarray=("item1" "item2")
printf "${myarray[@]}\n"

虽然function @() {}可以作为函数名称使用,但它应该被视为不好的做法。给函数一个实用的名称。能告诉用户其目的是什么的东西。