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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28114999/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 12:14:38  来源:igfitidea点击:

What are the rules for valid identifiers (e.g. functions, vars, etc) in Bash?

linuxbashunixsyntax

提问by labyrinth

What are the syntax rules for identifiers, especially function and variable names, in Bash?

Bash 中标识符的语法规则是什么,尤其是函数名和变量名?

I wrote a Bash script and tested it on various versions of Bash on Ubuntu, Debian, Red Hat 5 and 6, and even an old Solaris 8 box. The script ran well, so it shipped.

我编写了一个 Bash 脚本,并在 Ubuntu、Debian、Red Hat 5 和 6,甚至是旧的 Solaris 8 机器上的各种版本的 Bash 上对其进行了测试。脚本运行良好,所以它发货了。

Yet when a user tried it on SUSE machines, it gave a "not a valid identifier" error. Fortunately, my guess that there was an invalid character in the function name was right. The hyphens were messing it up.

然而,当用户在 SUSE 机器上尝试它时,它给出了“无效标识符”错误。幸运的是,我猜测函数名称中存在无效字符是正确的。连字符把它搞砸了。

The fact that a script that was at least somewhat tested would have completely different behaviour on another Bash or distro was disconcerting. How can I avoid this?

至少经过某种程度测试的脚本在另一个 Bash 或发行版上会有完全不同的行为,这一事实令人不安。我怎样才能避免这种情况?

回答by Thomas

From the manual:

手册

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

nameis defined elsewhere:

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.

So hyphens are not valid. And yet, on my system, they do work...

所以连字符是无效的。然而,在我的系统上,它们确实有效......

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

回答by rici

Command identifiers and variable names have different syntaxes. A variable name is restricted to alphanumeric characters and underscore, not starting with a digit. A command name, on the other hand, can be just about anything which doesn't contain bash metacharacters (and even then, they can be quoted).

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

In bash, function names can be command names, as long as they would be parsed as a WORD without quotes. (Except that, for some reason, they cannot be integers.) However, that is a bash extension. If the target machine is using some other shell (such as dash), it might not work, since the Posix standard shell grammar only allows "NAME" in the function definition form (and also prohibits the use of reserved words).

在 bash 中,函数名可以是命令名,只要它们会被解析为不带引号的 WORD。(除此之外,由于某种原因,它们不能是整数。)但是,这是一个 bash 扩展。如果目标机器正在使用其他一些 shell(例如 dash),它可能不起作用,因为 Posix 标准 shell 语法只允许在函数定义形式中使用“NAME”(并且还禁止使用保留字)。

回答by Ron Burk

The question was about "the rules", which has been answered two different ways, each correct in some sense, depending on what you want to call "the rules". Just to flesh out @rici's point that you can shove about any character in a function name, I wrote a small bash script to try to checkevery possible (0-255) character as a function name, as well as as the second character of a function name:

问题是关于“规则”的,已经有两种不同的方式回答,每种方式在某种意义上都是正确的,这取决于您想称之为“规则”的内容。只是为了充实@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 $Name(){ return 0; }; $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

I actually skip NUL (0x00), as that's the one character bash may object to finding in the input stream. The output from this script was:

我实际上跳过了 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!

Note that bash happily lets me name my function "[}{". Probably my code is not quite rigorous enough to provide the exact rules for legality-in-practice, but it should give a flavor of what manner of abuse is possible. I wish I could mark this answer "For mature audiences only."

请注意,bash 愉快地让我将函数命名为“[}{”。可能我的代码不够严谨,无法为实践中的合法性提供确切的规则,但它应该给出可能的滥用方式的味道。我希望我可以将这个答案标记为“仅限成熟观众”。

回答by Bastian Bittorf

This script tests all valid chars for function names with 1 char.

此脚本使用 1 个字符测试函数名称的所有有效字符。



It outputs 53valid chars (a-zA-Z and underscore) using
a POSIX shelland 220valid chars with BASHv4.4.12.

它输出53个使用有效的字符(A-ZA-Z和下划线)
POSIX壳220个具有有效字符BASHv4.4.12。

The Answer from Ron Burk is valid, but lacks the numbers.

Ron Burk 的答案是有效的,但缺少数字。

#!/bin/sh

FILE='/tmp/FOO'
I=0
VALID=0

while [ $I -lt 256 ]; do {
        NAME="$( printf \$( printf '%03o' $I ))"
        I=$(( I + 1 ))

        >"$FILE"
        ( eval "$NAME(){ rm $FILE;}; $NAME" 2>/dev/null )

        if [ -f "$FILE" ]; then
                rm "$FILE"
        else
                VALID=$(( VALID + 1 ))
                echo "$VALID/256 - OK: $NAME"   
        fi
} done

回答by Etan Reisner

From 3.3 Shell Functions:

来自3.3 Shell 函数

Shell functions are a way to group commands for later execution using a single name for the group. They are executed just like a "regular" command. When the name of a shell function is used as a simple command name, the list of commands associated with that function name is executed. Shell functions are executed in the current shell context; no new process is created to interpret them.

Functions are declared using this syntax:

name () compound-command [ redirections ]

or

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

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

使用以下语法声明函数:

name () compound-command [ redirections ]

或者

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

and from 2 Definitions:

和来自2 个定义

name

A word consisting solely of letters, numbers, and underscores, and beginning with a letter or underscore. Names are used as shell variable and function names. Also referred to as an identifier.

姓名

仅由字母、数字和下划线组成并以字母或下划线开头的单词。名称用作外壳变量和函数名称。也称为标识符。