В сценарии bash, что отличается между объявлением и нормальной переменной?

44

В скриптах bash:

мы создаем переменную, просто называя ее:

abc=ok

или мы можем использовать declare

declare abc=ok

какая разница?

и почему bash делает так много способов создать переменную?

lovespring
источник
6
Когда используется в функции, declareделает имена локальными, как с localкомандой. -gОпция подавляет такое поведение. См help declare.
Сайрус
2
declareпозволяет создавать ассоциативные массивы, целые числа и переменные только для чтения. Кроме того, он расширяет свои аргументы, поэтому такие вещи declare $name=1возможны.
Чороба

Ответы:

34

От help -m declare:

НАЗВАНИЕ

    declare - Установите значения переменных и атрибутов.

СИНТАКСИС

    declare[ -aAfFgilnrtux] [ -p] [ name[ ] ...]=value

ОПИСАНИЕ

    Установите значения переменных и атрибуты.

    Объявите переменные и дайте им атрибуты. Если имена не указаны, отобразите атрибуты и значения всех переменных.

    Опции:

      -f
        ограничить действие или отображение именами и определениями функций
      -F
        ограничить отображение только именами функций (плюс номер строки и исходный файл при отладке)
      -g
        создавать глобальные переменные при использовании в функции оболочки; в противном случае игнорируется
      -p
        отображать атрибуты и значение каждого ИМЯ

    Опции, которые устанавливают атрибуты:

      -a
        сделать NAMEs индексированными массивами (если поддерживается)
      -A
        сделать NAMEs ассоциативными массивами (если поддерживается)
      -i
        чтобы NAME имели атрибут integer
      -l
        преобразовывать имена в нижний регистр при назначении
      -n
        сделать NAME ссылкой на переменную, названную ее значением
      -r
        сделать имена только для чтения
      -t
        чтобы имена имели атрибут trace
      -u
        преобразовать имена в верхний регистр при назначении
      -x
        сделать экспорт NAMEs

    Использование ' +' вместо ' -' отключает данный атрибут.

    Переменные с целочисленным атрибутом имеют арифметическую оценку (см. letКоманду), выполняемую, когда переменной присваивается значение.

    Когда используется в функции, declareделает имена локальными, как с local командой. Опция ' -g' подавляет это поведение.

    Состояние выхода:
    возвращает успех, если не указана неверная опция или не произошла ошибка назначения переменной.

СМОТРИТЕ ТАКЖЕ

    Баш (1)

РЕАЛИЗАЦИЯ

    GNU bash, версия 4.3.11 (1) -релиз (i686-pc-linux-gnu)
    Copyright (C) 2013 Free Software Foundation, Inc.
    Лицензия GPLv3 +: GNU GPL версии 3 или новее <http://gnu.org/ лицензии / gpl.html>


Таким образом, declareиспользуется для установки значений переменных и атрибутов .

Позвольте мне показать использование двух атрибутов на очень простом примере:

$ # First Example:
$ declare -r abc=ok
$ echo $abc
ok
$ abc=not-ok
bash: abc: readonly variable


$ # Second Example:
$ declare -i x=10
$ echo $x
10
$ x=ok
$ echo $x
0
$ x=15
$ echo $x
15
$ x=15+5
$ echo $x
20

Из приведенного выше примера, я думаю, вы должны понимать использование declareпеременной над обычной переменной! Этот тип действия declareполезен в функциях, в циклах со сценариями.

Также зайдите в Переменные ввода: объявите или наберите

Pandya
источник
да, "и атрибуты" это точка! в этом разница.
родник
Большой! Я люблю примеры, лучший способ учить / учиться. Благодарность!
туркен
1
Вы должны знать, что такое «атрибуты», чтобы понять этот ответ. Это свойства переменной, такие как «целое число», «массив» или «только для чтения».
Нумен
11

abc=okприсваивает значение переменной abc. declare abcобъявляет переменную с именем abc. Два могут быть объединены как declare abc=ok.

В bash, как и в других оболочках, переменные строк и массивов не нужно объявлять, поэтому declareнет необходимости, если вы не хотите передавать параметры, например, declare -A abcчтобы создать abcассоциативный массив или declare -rсделать переменную доступной только для чтения. Тем не менее, внутри функции declareимеет значение: она вызывает переменную, чтобы быть локальной для функции, то есть значение переменной за пределами функции (если таковые имеются) сохраняется. (Если только вы не используете declare -g, что делает переменную не локальной, это полезно в сочетании с другими параметрами, например, declare -gAдля создания глобального ассоциативного массива в функции.) Пример:

f () {
  declare a
  a='a in f'
  b='b in f'
  echo "From f: a is $a"
  echo "From f: b is $b"
}
a='Initial a'
b='Initial b'
f
echo "After f: a is $a"
echo "After f: b is $b"

Выход:

From f: a is a in f
From f: b is b in f
After f: a is Initial a
After f: b is b in f

Еще одна вещь, которую вы можете сделать с помощью declareвстроенного

declareВстроенный является уникальной для Баша. Он сильно вдохновлен и очень близок к typesetвстроенному в ksh , а bash typesetявляется синонимом declareсовместимости. (Я не знаю, почему Bash не просто назвал это typeset). Есть третий синоним local. Кроме того export, есть то же самое, что declare -xи для совместимости (с каждой оболочкой в ​​стиле Борна).

Жиль "ТАК - перестань быть злым"
источник
да! «и вариант» это точка. ps если я спроектирую bash, я позволю поведению «объявить» сделать что-то в другом условии. это делает вещи простыми.
родник
Хороший ответ. Еще один вопрос, который один из export, localи declareявляется наиболее совместимым с другими оболочками?
0xc0de
1
@ 0xc0de exportсуществует во всех вариантах sh. localсуществует только в bash и zsh, declareтолько в bash. typesetсуществует в ksh, bash и zsh.
Жиль "ТАК - перестань быть злым"