Несколько назначений переменных, разделенных пробелом в одной строке в Bash

#bash #variable-assignment

#bash #переменная-назначение

Вопрос:

Для назначения переменных в bash я обычно делаю следующее:

 a=1
b=2
c=3
  

Если это выполняется в одной строке, это будет похоже:

 a=1; b=2; c=3
  

Недавно я видел некоторые коды, такие как:

 a=1 b=2 c=3
  

Назначение разделено пробелом, и оно работает. Я пытался использовать этот подход в Google, но не могу быстро найти ответ из учебника. Прямо сейчас я просто знаю, что это работает.

Итак, поддерживается ли этот синтаксис всеми оболочками или это стандартный подход?

Комментарии:

1. by all shell «вся оболочка» — что именно ? Их много

2. или «другой оболочкой (например, csh, ksh ..)» был бы лучшим термином.

3. Это явно поддерживается POSIX. Простой команде может предшествовать одно или несколько назначений, и «оператор присваивания» на самом деле является просто простой командой без фактической команды. См. Правила грамматики оболочки , в частности правило 7.

Ответ №1:

это стандартный подход?

ДА.

Из языка оболочки posix 2.9.1 Простые команды, выделение мое:

«Простая команда» — это последовательность необязательных назначений и перенаправлений переменных в любой последовательности, за которыми необязательно следуют слова и перенаправления, завершаемые управляющим оператором.

[…]

Если имя команды не отображается, присвоение переменных должно повлиять на текущую среду выполнения. […]

Это также видно из грамматики оболочки:

 simple_command   : cmd_prefix cmd_word cmd_suffix
                 | cmd_prefix cmd_word
                 | cmd_prefix
                 | cmd_name cmd_suffix
                 | cmd_name

cmd_prefix       :            io_redirect
                 | cmd_prefix io_redirect
                 |            ASSIGNMENT_WORD
                 | cmd_prefix ASSIGNMENT_WORD
  

Вы можете поместить столько назначений (и перенаправлений), сколько хотите, перед command . Если команды нет, назначения будут влиять на текущую оболочку.

Ответ №2:

Да, это работает. Возможным предостережением является SC2155 в том, что вы должны объявлять и назначать отдельно.

При этом это будет работать, за исключением использования нескольких параметров объявления между параметрами. Также обратите внимание, что параметры объявления будут применяться ко всем переменным (в данном случае -i).

script0:

 #!/bin/bash

declare a b c
a=foo
b=bar
c=baz

foo () {
    local a=1 b=2 c=3

    echo "From within func:"
    declare -p a
    declare -p b
    declare -p c
}

foo

echo "From outside func:"
declare -p a
declare -p b
declare -p c
Output:

$ ./script.sh
From within func:
declare -- a="1"
declare -- b="2"
declare -- c="3"
From outside func:
declare -- a="foo"
declare -- b="bar"
declare -- c="baz"
  

script1:

 #!/usr/bin/env bash

declare -i a -a b c
a=foo
b=(bar)
c=baz

foo () {
    local -i a=1 -a b=(2) c=3

    echo "From within func:"
    declare -p a
    declare -p b
    declare -p c
}

foo

echo "From outside func:"
declare -p a
declare -p b
declare -p c
Output:

$ ./script.sh
./script.sh: line 3: declare: `-a': not a valid identifier
./script.sh: line 9: local: `-a': not a valid identifier
From within func:
declare -i a="1"
declare -ai b=([0]="2")
declare -i c="3"
From outside func:
declare -i a="0"
declare -ai b=([0]="0")
declare -i c="0"
  

Ответ №3:

POSIX определяет простую команду как

«Простая команда» — это последовательность необязательных назначений и перенаправлений переменных в любой последовательности, за которыми необязательно следуют слова и перенаправления, завершаемые управляющим оператором.

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

Далее в том же разделе приводится семантика таких назначений без команд:

Назначение переменных должно выполняться следующим образом:

  • Если имя команды не отображается, присвоение переменных должно повлиять на текущую среду выполнения.