Bash中有效标识符(例如函数,variables等)的规则是什么?

在Bash中,标识符的语法规则是什么,特别是函数和variables名称?

我写了一个Bash脚本,并在Ubuntu,Debian,Red Hat 5和6甚至旧的Solaris 8盒子上的各种版本的Bash上进行了testing。 剧本运行良好,所以它运送。

然而,当用户在SUSE机器上试用时,它给出了“不是有效的标识符”的错误。 幸运的是,我猜测函数名中有一个无效的字符是正确的。 连字符被搞乱了。

事实上,至less有些testing的脚本在另一个Bash或发行版上会有完全不同的行为,这令人不安。 我怎样才能避免这一点?

Solutions Collecting From Web of "Bash中有效标识符(例如函数,variables等)的规则是什么?"

Shell Function Definitions ... name () compound-command [redirection] function name [()] compound-command [redirection] 

name在其他地方定义:

  name A word consisting only of alphanumeric characters and under‐ scores, and beginning with an alphabetic character or an under‐ score. Also referred to as an identifier. 

所以连字符是无效的。 然而,在我的系统上,他们工作…

 $ bash --version GNU bash, version 4.2.25(1)-release (x86_64-pc-linux-gnu) 

命令标识符和变量名称具有不同的语法。 变量名称仅限于字母数字字符和下划线,不能以数字开头。 另一方面,命令名可以是任何不包含bash元字符的东西(即使这样,它们也可以被引用)。

在bash中,函数名称可以是命令名称,只要它们被解析为不带引号的WORD即可。 (除了出于某种原因,它们不能是整数)。但是,这是一个bash扩展。 如果目标机器正在使用其他shell(如短划线),则可能无法正常工作,因为Posix标准shell语法仅在函数定义表单中允许使用“NAME”(也禁止使用保留字)。

从3.3 Shell函数 :

Shell函数是一种将命令分组以使用组的单个名称稍后执行的方法。 它们像“常规”命令一样执行。 当一个shell函数的名字被用作一个简单的命令名时,执行与该函数名相关的命令列表。 Shell函数在当前的shell上下文中执行; 没有新的过程被创造解释他们。

函数声明使用这个语法:

 name () compound-command [ redirections ] 

要么

 function name [()] compound-command [ redirections ] 

和来自2定义 :

名称

一个单词由字母,数字和下划线组成,以字母或下划线开头。 名称被用作shell变量和函数名称。 也被称为标识符。

问题是关于“规则”的问题,这个问题有两种不同的解决方法,每一种都有一定的正确性,取决于你想要的“规则”。 为了充实@ rici的观点,你可以在功能名称中推动任何字符,我写了一个小的bash脚本来试图检查每个可能的(0-255)字符作为函数名称,以及作为第二个字符一个函数名称:

 #!/bin/bash ASCII=( nul soh stx etx eot enq ack bel bs tab nl vt np cr so si dle \ dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us sp ) for((i=33; i < 127; ++i)); do printf -v Hex "%x" $i printf -v Chr "\x$Hex" ASCII[$i]="$Chr" done ASCII[127]=del for((i=128; i < 256; ++i)); do ASCII[$i]=$(printf "0X%x" $i) done # ASCII table is now defined function Test(){ Illegal="" for((i=1; i <= 255; ++i)); do Name="$(printf \\$(printf '%03o' $i))" eval "function $1$Name(){ return 0; }; $1$Name ;" 2>/dev/null if [[ $? -ne 0 ]]; then Illegal+=" ${ASCII[$i]}" # echo Illegal: "${ASCII[$i]}" fi done printf "Illegal: %s\n" "$Illegal" } echo "$BASH_VERSION" Test Test "x" # can we really do funky crap like this? function [}{(){ echo "Let me take you to, funkytown!" } [}{ # why yes, we can! # though editor auto-indent modes may punish us 

我实际上跳过NUL(0x00),因为这是bash可能反对在输入流中找到的一个字符。 这个脚本的输出是:

 4.4.0(1)-release Illegal: soh tab nl sp ! " # $ % & ' ( ) * 0 1 2 3 4 5 6 7 8 9 ; < > \ ` { | } ~ del Illegal: soh " $ & ' ( ) ; < > [ \ ` | del Let me take you to, funkytown! 

请注意,bash高兴地让我命名我的功能“[} {”。 大概我的代码不够严谨,不能提供合法实践的确切规则,但应该给出一种滥用方式的可能性。 我希望我能标记这个答案“仅适用于成熟的观众”。