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

18

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

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

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

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

    
задан labyrinth 23.01.2015 в 18:04
источник
  • Какая версия bash была на этих машинах? (В частности, машина SUSE?) –  Etan Reisner 23.01.2015 в 18:05
  • К сожалению, сейчас у меня нет простого доступа. Они были 3.что-то. –  labyrinth 26.01.2015 в 16:25

4 ответа

18
   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)
    
ответ дан Thomas 23.01.2015 в 18:07
источник
6

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

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

    
ответ дан rici 23.01.2015 в 18:14
источник
  • Однако машины SUSE использовали Bash (в соответствии с echo $ SHELL). Я не уверен, почему он был недоволен дефисом, когда на складе Bash другие крупные дистрибутивы не волновало. –  labyrinth 26.01.2015 в 16:23
  • @labyrinth: «echo $ SHELL» не сообщает вам, какая оболочка выполняется. Он сообщает вам, что такое оболочка по умолчанию текущего пользователя. Поэтому вполне возможно, что команда запускалась в другой оболочке по какой-либо причине (например, она была в скрипте, начинающемся с строки shebang с #! / Bin / sh). Другая возможность, хотя кажется менее вероятной, заключается в том, что сценарий работал в оболочке posix, либо потому, что была установлена ​​переменная среды POSIXLY_CORRECT, либо потому, что был установлен set -p, либо -p был включен в параметры командной строки для bash. –  rici 26.01.2015 в 21:44
  • нет, в скрипте нет строки shebang, поэтому, если бы она не использовала оболочку входа по умолчанию, она должна была быть другой причиной. –  labyrinth 26.01.2015 в 23:41
  • @labyrinth: если сценарий не имеет строки shebang, тогда он не определен, какая оболочка будет вызываться для его выполнения. Это может быть / bin / sh (что является поведением вызова библиотеки execlp), или это может быть текущая оболочка (bash и ksh обрабатывают строки shebang таким образом.) Если скрипт был явно вызван с помощью sh-скрипта, то из Конечно, это будет sh, который выполняет его, независимо от линии shebang или $ SHELL. –  rici 27.01.2015 в 01:08
3
Вопрос был о «правилах», на которые ответили два разных способа, каждый из которых в некотором смысле правильный, в зависимости от того, что вы хотите назвать «правилами». Просто для того, чтобы выразить точку @ 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

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

    
ответ дан Ron Burk 18.05.2017 в 09:33
источник
  • Было бы полезно включить версию Bash, с которой вы запускали свой скрипт. –  dimo414 21.03.2018 в 07:35
  • Вы не можете определить функцию с полным номером, но можете начать с числа. Кроме того, некоторые из предполагаемых незаконностей здесь вызваны плохим цитированием при вызове функции. Например, вы можете назвать функцию * ... но, как это делает этот тест, она вызывает ошибку. Таким образом, фактический список символов, которые вы не можете иметь в первом месте имени функции, меньше, чем список здесь ... но список символов второго места длиннее, потому что снова этот скрипт не вызывает функцию правильно. –  PJ Eby 30.03.2018 в 02:34
2

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

  

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

     

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

name () compound-command [ redirections ]
     

или

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

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

  

имя

     

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

    
ответ дан Etan Reisner 23.01.2015 в 18:08
источник