Правильное использование заглавных букв в сценариях Bash и shell

193

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

Но в современных средах написания сценариев, таких как Bash, я всегда предпочитал использовать строчные имена для временных переменных, а заглавные только для экспортированных (то есть окружающих) переменных . Например:

#!/usr/bin/env bash
year=`date +%Y`
echo "It is $year."
export JAVA_HOME="$HOME/java"

Это всегда был мой взгляд на вещи. Существуют ли авторитетные источники, которые либо соглашаются, либо не соглашаются с этим подходом, или это просто вопрос стиля?

JasonSmith
источник

Ответы:

262

По соглашению, переменные окружения ( PAGER, EDITOR, ...) и внутренних переменных оболочки ( SHELL, BASH_VERSION, ...) капитализируются. Все остальные имена переменных должны быть в нижнем регистре.

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

Соблюдая это соглашение, вы можете быть уверены, что вам не нужно знать каждую переменную среды, используемую инструментальными средствами или оболочками UNIX, чтобы избежать их перезаписи. Если это ваша переменная, строчные. Если вы экспортируете его, используйте его в верхнем регистре.

lhunath
источник
8
+1. Хороший момент о случайной перезаписи. Я забыл упомянуть, но теперь, когда вы упомянули об этом, я решил использовать строчные буквы, потому что я читал или слышал только об этой проблеме.
Джейсон Смит
5
Я думал, что основная причина использования имен переменных в верхнем регистре заключается в том, чтобы избежать конфликтов с командами оболочки. Недавно у нас было случайно изменено имя хоста одного из наших серверов на «=», потому что скрипт использовал переменную «имя хоста».
ThisSuitIsBlackNot
25
@ThisSuitIsBlackNot Игнорируя дрянной код, переменные имеют префикс с долларом при расширении и используются в месте, где их нельзя спутать с именем команды, когда это не так. Очевидно, что выполнение hostname = moo приведет к неприятностям. Не потому, что вы используете «имя хоста» в нижнем регистре, а потому, что вы не используете правильный синтаксис присваивания. Назначение выполняется с именем хоста = moo, без пробелов. Принимая правильный код, вам не нужно беспокоиться о именах переменных, конфликтующих с именами команд.
лунат
3
Все учебники, которые я просматривал, всегда были прописными для всех переменных оболочки. Хотя имена переменных в нижнем регистре допустимы, в верхнем регистре это соглашение.
Брайан С. Уилсон
3
Я не знал этого, и я просто потерял пару часов. использование USER="username"в скрипте bash автоматизации некоторых удаленных команд через ssh вместо user="username". Тьфу! Рад, что знаю сейчас!
Габриэль Стейплз
28

Любые соглашения о присвоении имен, соблюдаемые последовательно, всегда помогут. Вот несколько полезных советов для именования переменных оболочки:

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

    Примеры:

    • Экспортируемые переменные с общим префиксом: JOB_HOME JOB_LOG JOB_TEMP JOB_RUN_CONTROL
    • Константы: LOG_DEBUG LOG_INFO LOG_ERROR STATUS_OK STATUS_ERROR STATUS_WARNING
  • Используйте «случай змеи» ( все строчные и подчеркивания ) для всех переменных, которые ограничены одним скриптом или блоком.

    Примеры: input_file first_value max_amount num_errors

    Используйте смешанный случай, когда локальная переменная имеет некоторую связь с переменной окружения, например: old_IFS old_HOME

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

    Примеры: _debug _debug_level _current_log_file

  • Избегайте случая верблюда . Это минимизирует ошибки, вызванные опечатками. Помните, что переменные оболочки чувствительны к регистру .

    Примеры: inputArray thisLooksBAD, numRecordsProcessed,veryInconsistent_style


Смотрите также:

codeforester
источник
1
Это условность , но оно вряд ли общепризнанное. Обоснование против верблюжьего дела не совсем убедительно. Рекомендации по использованию КРИКУ для экспортируемых переменных умеренно спорные.
tripleee
3
Я не заявлял, что это общепринятая конвенция. Я видел, что большинство программистов не думают всерьез о следовании строгим соглашениям в сценариях оболочки и думали записать мои мысли, основанные на том, что я делал.
Codeforester
8

Если переменные оболочки будут экспортированы в среду, стоит учесть, что в определении переменной среды POSIX (выпуск 7, выпуск 2018) указано:

Имена переменных среды, используемые утилитами в томе Shell и Utilities POSIX.1-2017, состоят исключительно из заглавных букв, цифр и _символа подчеркивания ( ) из символов, определенных в переносимом наборе символов, и не начинаются с цифры.

...

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

Энтони Геогеган
источник
6

Я делаю то, что ты делаешь. Я сомневаюсь, что есть авторитетный источник, но де-факто это довольно распространенный стандарт.

Draemon
источник
1
Я согласен. Это потому, что ALL_CAPS уродлив, но хорошо, чтобы отличать СРЕДЫ ПЕРЕМЕННЫХ от того, что они уродливы.
тонкий
1
Я согласен с вами в отношении стиля кодирования, но я определенно не согласен с тем, что он широко распространен! Сценарии оболочки - это один из тех дополнительных языков, которые люди просто неформально изучают, и поэтому я чувствую, что все всегда говорят: МЕСТО =cat /tmp/location.txt
JasonSmith,
@jhs - мне явно повезло в сценариях оболочки, с которыми мне приходилось работать!
Draemon
4
«Пространство имен имен переменных среды, содержащих строчные буквы, зарезервировано для приложений». - POSIX IEEE Std 1003.1-2008, раздел 8.1
tripleee
5

На самом деле, термин «переменные среды», кажется, имеет довольно недавнюю чеканку. Керниган и Пайк в своей классической книге «Среда программирования UNIX», опубликованной в 1984 году, говорят только о «переменных оболочки» - в индексе даже нет записи о «среде»!


источник
8
Я думаю, что это упущение книги. getenv (), setenv () и environment были введены в UNIX версии 7 (1979). en.wikipedia.org/wiki/Version_7_Unix
Джулиано,
3
В этой книге отмечается, что переменные верхнего регистра имеют особое значение.
Эшоули
3

Это просто очень широко распространенное соглашение, я сомневаюсь, что есть какой-либо «авторитетный» источник для него.

Альнитак
источник
1

Я склонен использовать ALL_CAPS как для окружающей среды, так и для глобальных переменных. Конечно, в Bash нет реальной области видимости переменных, поэтому есть большая часть переменных, используемых в качестве глобальных переменных (в основном это настройки и отслеживание состояния), и относительно немного «локальных» (счетчики, итераторы, частично построенные строки и временные переменные)

Хавьер
источник
Да, я как бы концептуально представляю неэкспортированные переменные как локальные, поскольку Bash так часто разветвляет дочерние процессы, чтобы делать то, что ему поручено делать.
Джейсон Смит