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

后端 未结 5 596
终归单人心
终归单人心 2020-12-03 17:02

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

I wrote a Bash script and tested it on various versions of Bash on Ubuntu

相关标签:
5条回答
  • 2020-12-03 17:19

    From the manual:

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

    name is defined elsewhere:

           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)
    
    0 讨论(0)
  • 2020-12-03 17:19

    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).

    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).

    0 讨论(0)
  • 2020-12-03 17:23

    From 3.3 Shell Functions:

    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 ]
    

    and from 2 Definitions:

    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.

    0 讨论(0)
  • 2020-12-03 17:26

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


    It outputs 53 valid chars (a-zA-Z and underscore) using
    a POSIX shell and 220 valid chars with BASH v4.4.12.

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

    #!/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
    
    0 讨论(0)
  • 2020-12-03 17:34

    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:

    #!/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. 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 "[}{". 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."

    0 讨论(0)
提交回复
热议问题