简体   繁体   English

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

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

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.我编写了一个 Bash 脚本,并在 Ubuntu、Debian、Red Hat 5 和 6,甚至是旧的 Solaris 8 机器上的各种版本的 Bash 上对其进行了测试。 The script ran well, so it shipped.脚本运行良好,所以它发货了。

Yet when a user tried it on SUSE machines, it gave a "not a valid identifier" error.然而,当用户在 SUSE 机器上尝试它时,它给出了“无效标识符”错误。 Fortunately, my guess that there was an invalid character in the function name was right.幸运的是,我猜测函数名称中存在无效字符是正确的。 The hyphens were messing it up.连字符把它搞砸了。

The fact that a script that was at least somewhat tested would have completely different behaviour on another Bash or distro was disconcerting.至少经过某种程度测试的脚本在另一个 Bash 或发行版上会有完全不同的行为,这一事实令人不安。 How can I avoid this?我怎样才能避免这种情况?

From the manual :手册

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

name is 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)

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 check every 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 $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

I actually skip NUL (0x00), as that's the one character bash may object to finding in the input stream.我实际上跳过了 NUL (0x00),因为这是 bash 可能反对在输入流中查找的一个字符。 The output from this script was:这个脚本的输出是:

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 "[}{".请注意,bash 很高兴让我将函数命名为“[}{”。 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."我希望我可以将这个答案标记为“仅限成熟观众”。

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.在 bash 中,函数名可以是命令名,只要它们会被解析为不带引号的 WORD。 (Except that, for some reason, they cannot be integers.) However, that is a bash extension. (除了出于某种原因,它们不能是整数。)但是,这是一个 bash 扩展。 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).如果目标机器正在使用其他一些 shell(例如 dash),它可能不起作用,因为 Posix 标准 shell 语法只允许在函数定义形式中使用“NAME”(并且还禁止使用保留字)。

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. Shell 函数是一种将命令分组以便以后执行的方法,使用组的单个名称。 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 函数的名称用作简单的命令名称时,将执行与该函数名称关联的命令列表。 Shell functions are executed in the current shell context; Shell 函数在当前 Shell 上下文中执行; no new process is created to interpret them.没有创建新的过程来解释它们。

Functions are declared using this syntax:使用以下语法声明函数:

 name () compound-command [ redirections ]

or或者

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.也称为标识符。

This script tests all valid chars for function names with 1 char.此脚本使用 1 个字符测试函数名称的所有有效字符。


It outputs 53 valid chars (a-zA-Z and underscore) using它使用以下方法输出53 个有效字符(a-zA-Z 和下划线)
a POSIX shell and 220 valid chars with BASH v4.4.12. BASH v4.4.12 的POSIX shell220 个有效字符。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Bash:检查是否给出了参数(例如,是否有参数“-a”?) - Bash: Check if argument is given (e.g. is there the argument "-a" ?) 拆分字符串(例如使用bash)但跳过部分字符串 - split string (e.g. with bash) but skip part of it 在 unix/linux 命令行中定义函数(例如 BASH) - Define function in unix/linux command line (e.g. BASH) 有name.d /目录(例如/etc/httpd/conf.d)吗? - Is there a name for name.d/ (e.g. /etc/httpd/conf.d) directories? 一个演示cmd.exe和Linux shell(例如bash),定界参数的AC程序? - A C program demonstrating how cmd.exe and a linux shell e.g. bash, delimit parameters? 如何在Bash / shell中将某些符号(例如“空格”)更改为其他符号 - How to change some symbols (e.g. “space”) to other symbol in Bash/shell 包含例如 git-branch(1) 的手册页的含义是什么 - What is the meaning of man pages contaning e.g. git-branch(1) Linux程序(例如bash或python脚本)如何知道它是如何启动的:从命令行还是交互式GUI? - How can Linux program, e.g. bash or python script, know how it was started: from command line or interactive GUI? 如何在 bash 脚本中的流水线命令之间插入延迟。 例如猫文件| 远程登录 mail.domain.com 25 - How to insert a delay between pipelining commands in a bash script. E.g. cat file | telnet mail.domain.com 25 sed -e &#39;s|PATH=&quot;\(.*\)&quot;|PATH=&quot;/opt/man/common/bin:\1&quot;|g&#39; -i /etc/environment 行是什么意思 - what is meaning of sed -e 's|PATH="\(.*\)"|PATH="/opt/man/common/bin:\1"|g' -i /etc/environment line
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM