Правильное использование переменных может придать сценариям дополнительную мощь и гибкость, а для этого необходимо изучить все тонкости и нюансы.
9.1. Внутренние переменные
путь к исполняемому файлу Bash
это массив, состоящий из 6 элементов, и содержащий информацию о версии Bash. Очень похожа на переменную $BASH_VERSION, описываемую ниже.
версия Bash, установленного в системе
Проверка переменной $BASH_VERSION — неплохой метод проверки типа командной оболочки, под которой исполняется скрипт. Переменная $SHELL не всегда дает правильный ответ.
содержимое вершины стека каталогов (который управляется командами pushd и popd)
Эта переменная соответствует команде dirs, за исключением того, что dirs показывает полное содержимое всего стека каталогов.
заданный по-умолчанию редактор, вызываемый скриптом, обычно vi или emacs.
«эффективный» идентификационный номер пользователя (Effective User ID)
Идентификационный номер пользователя, права которого были получены, возможно с помощью команды su.
Значение переменной $EUID необязательно должно совпадать с содержимым переменной $UID.
имя текущей функции
Перечень шаблонных символов, которые будут проигнорированы при выполнении подстановки имен файлов (globbing) .
группы, к которым принадлежит текущий пользователь
Это список групп (массив) идентификационных номеров групп для текущего пользователя, как эо записано в /etc/passwd.
домашний каталог пользователя, как правило это /home/username (см. Пример 9-13)
Сетевое имя хоста устанавливается командой hostname во время исполнения инициализирующих сценариев на загрузке системы. Внутренняя переменная $HOSTNAME Bash получает свое значение посредством вызова функции gethostname(). См. так же Пример 9-13.
Подобно $MACHTYPE, идентифицирует аппаратную архитектуру.
разделитель полей во вводимой строке (IFS — Input Field Separator)
По-умолчанию — пробельный символ (пробел, табуляция и перевод строки), но может быть изменен, например, для разбора строк, в которых отдельные поля разделены запятыми. Обратите внимание: при составлении содержимого переменной $*, Bash использует первый символ из $IFS для разделения аргументов. См. Пример 5-1.
При всем при том следует помнить, что при использовании $IFS пробельные символы обрабатываются несколько иначе, чем все остальные.
Пример 9-1. $IFS и пробельные символы
(Спасибо S. C., за разъяснения и примеры.)
Чаще всего устанавливается в .bashrc или /etc/profile, эта переменная задает порядок сортировки символов, в операциях подстановки имен файлов и в поиске по шаблону. При неверной настройке переменной LC_COLLATE можно получить весьма неожиданные результаты.
Начиная с версии 2.05, Bash, в операциях подстановки имен файлов, не делает различий между символами верхнего и нижнего регистров, в диапазонах символов в квадратных скобках. Например,, ls [A-M]* выведет как File1.txt, так и file1.txt. Возврат к общепринятому стандарту поведения шаблонов в квадратных скобках выполняется установкой переменной LC_COLLATE в значение C командой export LC_COLLATE=C в файле /etc/profile и/или
Эта внутренняя переменная определяет кодировку символов. Используется в операциях подстановки и поиске по шаблону.
Номер строки исполняемого сценария. Эта переменная имеет смысл только внутри исполняемого сценария и чаще всего применяется в отладочных целях.
Идентификатор аппаратной архитектуры.
прежний рабочий каталог ( «OLD-Print-Working-Directory» )
тип операционной системы
путь поиска, как правило включает в себя каталоги /usr/bin/, /usr/X11R6/bin/, /usr/local/bin, и т.д.
Когда командный интерпретатор получает команду, то он автоматически пытается отыскать соответствующий исполняемый файл в указанном списке каталогов (в переменной $PATH). Каталоги, в указанном списке, должны отделяться друг от друга двоеточиями. Обычно, переменная $PATH инициализируется в /etc/profile и/или в
Инструкция PATH=$:/opt/bin добавляет каталог /opt/bin в конец текущего пути поиска. Иногда может оказаться целесообразным, внутри сценария, временно добавить какой-либо каталог к пути поиска. По завершении работы скрипта, эти изменения будут утеряны (вспомните о том, что невозможно изменить переменные окружения вызывающего процесса).
Текущий «рабочий каталог» , ./, обычно не включается в $PATH из соображений безопасности.
Код возврата канала (конвейера). Интересно, что это не то же самое, что код возврата последней исполненной команды.
Переменная $PIPESTATUS может давать неверные значения при вызове из командной строки.
Если поместить эти строки в сценарий и исполнить его, то будут выведены верные значения 0 1 0.
Спасибо Wayne Pollock за замечания и предоставленный пример.
Вторичное приглашение командной строки, выводится тогда, когда от пользователя ожидается дополнительный ввод. Отображается как «>» .
Третичное приглашение (prompt), выводится тогда, когда пользователь должен сделать выбор в операторе select (см. Пример 10-29).
Приглашение (prompt) четвертого уровня, выводится в начале каждой строки вывода тогда, когда сценарий вызывается с ключом -x . Отображается как «+» .
рабочий (текущий) каталог
Аналог встроенной команды pwd.
переменная по-умолчанию, куда записывается ввод пользователя, выполненный с помощью команды read если явно не задана другая переменная. Так же может использоваться в операторе select, для построения меню выбора.
Время паботы сценария в секундах.
список допустимых опций интерпретатора shell. Переменная доступна только для чтения.
Уровень вложенности shell. Если в командной строке
дает 1, то в сценарии значение этой переменной будет больше на 1, т.е. 2.
Если переменная окружения $TMOUT содержит ненулевое значение, то интерпретатор будет ожидать ввод не более чем заданное число секунд, что, в первичном приглашении (см. описание PS1 выше), может привести к автоматическому завершению сеанса работы.
К сожалению это возможно только во время ожидания ввода с консоли или в окне терминала. А как было бы здорово, если бы можно было использовать эту внутреннюю переменную, скажем в комбинации с командой read! Но в данном контексте эта переменная абсолютно не применима и потому фактически бесполезна в сценариях. (Есть сведения о том, что в ksh время ожидания ввода командой read можно ограничить.)
Организация ограничения времени ожидания ввода от пользователя в сценариях возможна, но это требут довольно сложных махинаций. Как один из вариантов, можно предложить организовать прерывание цикла ожидания по сигналу. Но это потребует написание функции обработки сигналов командой trap (см. Пример 29-5).
Пример 9-2. Ограничения времени ожидания ввода
В качестве альтернативы можно использовать stty.
Пример 9-3. Еще один пример ограничения времени ожидания ввода от пользователя
Возможно самый простой способ — использовать опцию -t команды read.
Пример 9-4. Ограничение времени ожидания команды read
UID (идентификатор) текущего пользователя, в соответствии с /etc/passwd
Это реальный UID текущего пользователя, даже если он временно приобрел права другого пользователя с помощью su. Переменная $UID доступна только для чтения.
Пример 9-5. Я — root?
Переменные $ENV, $LOGNAME, $MAIL, $TERM, $USER и $USERNAME, не являются встроенными переменными Bash. Тем не менее, они часто инициализируются как переменные окружения в одном из стартовых файлов Bash. Переменная $SHELL, командная оболочка пользователя, может задаваться в /etc/passwd или в сценарии «init» и она тоже не является встроенной переменной Bash.
Позиционные параметры (аргументы)
аргументы передаются. из командной строки в сценарий, функциям или команде set (см. Пример 4-5 и Пример 11-13)
количество аргументов командной строки [2] , или позиционных параметров (см. Пример 33-2)
Все аргументы в виде одной строки (слова)
То же самое, что и $* , но при этом каждый параметр представлен как отдельная строка (слово), т.е. параметры не подвергаются какой либо интерпретации.
Пример 9-6. arglist: Вывод списка аргументов с помощью переменных $* и $@
После команды shift (сдвиг), первый аргумент, в переменной $@, теряется, а остальные сдвигаются на одну позицию «вниз» (или «влево», если хотите).
Специальная переменная $@ может быть использована для выбора типа ввода в сценария. Команда cat «$@» позволяет выполнять ввод как со стандартного устройства ввода stdin, так и из файла, имя которого передается сценарию из командной строки. См. Пример 12-17 и Пример 12-18.
Переменные $* и $@, в отдельных случаях, могут содержать противоречивую информацию! Это зависит от содержимого переменной $IFS.
Пример 9-7. Противоречия в переменных $* и $@
Различия между $@ и $* наблюдаются только тогда, когда они помещаются в двойные кавычки.
Пример 9-8. Содержимое $* и $@, когда переменная $IFS — пуста
Прочие специальные переменные
Список флагов, переданных сценарию (командой set). См. Пример 11-13.
Эта конструкция изначально была введена в ksh , откуда перекочевала в Bash и, похоже, работает в Bash не совсем надежно. Единственное возможное применение — проверка — запущен ли сценарий в интерактивном режиме.
PID последнего, запущенного в фоне, процесса
Специальная переменная, содержит последний аргумент предыдущей команды.
Пример 9-9. Переменная «подчеркивание»
PID самого процесса-сценария. Переменная $$ часто используется при генерации «уникальных» имен для временных файлов (см. Пример A-14, Пример 29-6, Пример 12-23 и Пример 11-23). Обычно это проще чем вызов mktemp.
Примечания
PID текущего процесса хранится в переменной $$.
Слова «аргумент» и «параметр» очень часто используются как синонимы. В тексте данного документа, они применяются для обозначения одного и того же понятия, будь то аргумент, передаваемый скрипту из командной строки или входной параметр функции.
Источник
Как определить, пуста ли переменная bash?
Каков наилучший способ определить, является ли переменная в bash пустой («»)?
Я слышал, что мне рекомендуется if [ «x$variable» = «x» ]
Это правильный способ? (должно быть что-то более прямолинейное)
12 ответов
Это вернет true, если переменная не установлена или установлена в пустую строку («»).
В Bash, когда вы не занимаетесь переносимостью оболочек, которые его не поддерживают, вы всегда должны использовать синтаксис с двойной скобкой:
Любое из следующего:
В Bash, используя двойные квадратные скобки, цитаты не нужны. Вы можете упростить тест для переменной, в которой содержит значение:
Этот синтаксис совместим с ksh (по крайней мере, ksh93, во всяком случае). Он не работает в чистых POSIX или более старых оболочках Bourne, таких как sh или тире.
См. мой ответ здесь и BashFAQ /031 для получения дополнительной информации о различиях между двойными и одиночными квадратными скобками.
Вы можете проверить, не изменилась ли переменная (в отличие от пустой строки):
, где «x» произвольно.
Если вы хотите узнать, является ли переменная нулевой, но не отменяется:
Переменная в bash (и любая совместимая с POSIX оболочка) может находиться в одном из трех состояний:
снята с охраны
установить в пустую строку
установить непустую строку
В большинстве случаев вам нужно только знать, установлена ли переменная в непустую строку, но иногда важно различать unset и задавать пустую строку.
Ниже приведены примеры того, как вы можете тестировать различные возможности, и работает в bash или любой совместимой с POSIX оболочке:
Вот то же самое, но в удобной форме таблицы:
Конструкция $ расширяется до пустой строки, если VAR не установлен или foo , если VAR устанавливается на что угодно (включая пустую строку).
Конструкция $ расширяется до значения VAR , если установлена (в том числе установлена пустая строка) и foo если не установлено. Это полезно для предоставления пользовательских значений по умолчанию (например, $ говорит, чтобы использовать red , если не была выбрана переменная COLOR на что-то).
Причина, по которой [ x»$» = x ] часто рекомендуется для проверки того, является ли переменная либо отключена, либо установлена в пустую строку, потому что некоторые реализации кода [ (также известная как test ) ошибочна. Если для VAR установлено что-то вроде -n , то некоторые реализации будут делать не то, что указано [ «$» = «» ] , потому что первый аргумент [ ошибочно интерпретируется как оператор -n , а не строка.
-z — лучший способ.
Другими параметрами, которые я использовал, является установка переменной, но ее можно переопределить другой переменной, например
Если переменная $MY_PORT пуста, то PORT устанавливается значение 5432, в противном случае для параметра PORT установлено значение MY_PORT . Обратите внимание, что синтаксис включает двоеточие и тире.
Если вам интересно различать случаи состояния set-empty или unset, посмотрите на параметр -u для bash:
Альтернативный вариант, который я видел в [ -z «$foo» ] , является следующим, однако я не уверен, почему люди используют этот метод, кто-нибудь знает?
В любом случае, если вы не разрешаете отменять переменные (либо с помощью set -u , либо set -o nounset ), тогда у вас возникнут проблемы с обоими из этих методов , Это простое решение:
Примечание: это оставит вашу переменную undef.
вопрос запрашивает , как проверить, является ли переменная пустой строкой , и для нее уже даны лучшие ответы. Но я приземлился здесь после периода, прошедшего программирование в php, и то, что я на самом деле искал, было проверкой, как функция empty в php , работающая в оболочке bash. После прочтения ответов я понял, что я не думал правильно в bash, но так или иначе в этот момент функция, подобная empty в php, была бы очень удобной в моем коде bash. Как я думаю, это может случиться с другими, я решил преобразовать функцию php empty в bash
В соответствии с руководством по php : переменная считается пустым, если он не существует или его значение является одним из следующих:
«» (пустая строка)
0 (0 как целое число)
0.0 (0 в качестве поплавка)
«0» (0 в виде строки)
пустой массив
объявленная переменная, но без значения
Конечно, случаи null и false не могут быть преобразованы в bash, поэтому они опущены.
Демо-версия: следующий фрагмент:
Сказав, что в логике bash проверки на ноль в этой функции могут вызвать побочные проблемы imho, любой, кто использует эту функцию, должен оценить этот риск и, возможно, решит сократить эти проверки, оставив только первый.