今天我在bash中发现了一个奇怪的行为。
使用以下语法在交互式shell中定义名为“@”的函数时:
$ function @() { echo foo; }
它(当然)定义了一个名为“@”的函数。
但是,在特定情况下,例如在tmux会话或虚拟控制台中( Ctrl + Alt + F1 ),这定义了一个名为“@()”的函数。
我在这些环境中找不到任何差异(echo $-
的输出为himBH
)。此外,function @ { echo bar; }
没有此陷阱,并在两种情况下定义“@”。我找不到任何文件说@是bash中的特殊符号。
有人对此有所了解吗? 我在香草Ubuntu 16.04.2上证实了这些。
答案 0 :(得分:4)
“问题”是由shell选项extglob
引起的。
[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 {}
是函数名称。
@()
当[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 @() {}
可以作为函数名称使用,但它应该被视为不好的做法。给函数一个实用的名称。能告诉用户其目的是什么的东西。