Каковы правила для действительных идентификаторов (например, функций, vars и т.д.) В Bash?

Каковы правила синтаксиса для идентификаторов, особенно имена функций и переменных, в Bash?

Я написал Bash script и протестировал его в различных версиях Bash на Ubuntu, Debian, Red Hat 5 и 6 и даже в старом окне Solaris 8. script работал хорошо, поэтому он отправлен.

Однако, когда пользователь попробовал его на машинах SUSE, он дал ошибку "недействительный идентификатор". К счастью, я предполагал, что был неправильный символ в имени функции. Дефис был испорчен.

Тот факт, что a script, который был хотя бы несколько протестирован, имел бы совершенно другое поведение на другом Bash, или distro вызывал смущение. Как я могу избежать этого?

Ответы

Ответ 1

Из руководства:

   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)

Ответ 2

Идентификаторы команд и имена переменных имеют разные синтаксисы. Имя переменной ограничено буквенно-цифровыми символами и подчеркиванием, а не цифрой. С другой стороны, имя команды может быть почти тем, что не содержит bash метасимволов (и даже тогда их можно процитировать).

В bash имена функций могут быть именами команд, если они будут анализироваться как WORD без кавычек. (За исключением того, что по какой-то причине они не могут быть целыми числами.) Однако это расширение bash. Если целевая машина использует какую-либо другую оболочку (например, тире), она может не работать, поскольку стандартная грамматика оболочки Posix разрешает "NAME" в форме определения функции (а также запрещает использование зарезервированных слов).

Ответ 3

Вопрос был о "правилах", на которые ответили два разных способа, каждый из которых в некотором смысле правильный, в зависимости от того, что вы хотите назвать "правилами". Чтобы точно определить, что вы можете толкнуть любого персонажа в имени функции, я написал небольшой bash script, чтобы попытаться проверить все возможные (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 может помешать поиску во входном потоке. Выход из этого script был:

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 счастливо позволяет мне назвать мою функцию "[} {". Вероятно, мой код не достаточно строг, чтобы обеспечить точные правила законности в практике, но он должен придать вкус того, как можно злоупотреблять. Хотелось бы отметить этот ответ "Только для зрелых зрителей".

Ответ 4

От 3.3 Функции оболочки:

Функции оболочки - это способ группировки команд для последующего выполнения с использованием единственного имени для группы. Они выполняются так же, как "обычная" команда. Когда имя функции оболочки используется как простое имя команды, выполняется список команд, связанных с этим именем функции. Функции оболочки выполняются в текущем контексте оболочки; для их интерпретации не создается новый процесс.

Функции объявляются с использованием этого синтаксиса:

name () compound-command [ redirections ]

или

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

и 2 Определения:

имя

Слово, состоящее исключительно из букв, цифр и подчеркиваний, и начинается с буквы или подчеркивания. Имена используются как имена переменных оболочки и функции. Также упоминается как идентификатор.

Ответ 5

Этот скрипт проверяет все допустимые символы для имен функций с 1 символом.


Он выводит 53 действительных символа (a-zA-Z и подчеркивание), используя
оболочка POSIX и 220 действительных символов с BASH v4.4.12.

Ответ от Рона Бурка действителен, но в нем отсутствуют цифры.

#!/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