Разное

Bash переменные: Как использовать переменные Bash | Losst

Содержание

Семь неожиданных переменных Bash / Хабр

Продолжая серию заметок о менее известных функциях bash, покажу вам семь переменных, о которых вы могли не знать.

1) PROMPT_COMMAND

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

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

Попробуйте запустить это в новом шелле, и увидите, что произойдёт с сессией:

$ PROMPT_COMMAND='echo -n "writing the prompt at " && date'

2) HISTTIMEFORMAT

Если запустить history в консоли, вы получите список команд, ранее выполненных под вашей учётной записью.

$ HISTTIMEFORMAT='I ran this at: %d/%m/%y %T '

Как только установлена эта переменная, новые записи записывают время вместе с командой, поэтому выдача будет выглядеть так:

1871  I ran this at: 01/05/19 13:38:07 cat /etc/resolv. conf
1872  I ran this at: 01/05/19 13:38:19 curl bbc.co.uk
1873  I ran this at: 01/05/19 13:38:41 sudo vi /etc/resolv.conf
1874  I ran this at: 01/05/19 13:39:18 curl -vvv bbc.co.uk
1876  I ran this at: 01/05/19 13:39:25 sudo su -

Форматирование соответствует символам из man date.

3) CDPATH

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

Как и PATH, переменная CDPATH представляет собой список путей, разделённых двоеточием. Когда вы запускаете команду cd с относительным путём (т. е. без слэша в начале), по умолчанию оболочка ищет в вашей локальной папке соответствующие имена. CDPATH будет искать в путях, которые вы дали для каталога, куда хотите перейти.

Если установить CDPATH таким образом:

$ CDPATH=/:/lib

а затем ввести:

$ cd /home
$ cd tmp

то вы всегда попадёте в /tmp независимо от того, где находитесь.

Однако осторожно, потому что если не указать в списке локальную (.) папку, то вы не сможете создать любую другую папку tmp и перейти к ней, как обычно:

$ cd /home
$ mkdir tmp
$ cd tmp
$ pwd
/tmp

Упс!

Это похоже на путаницу, которую я почувствовал, когда понял, что локальная папка не была включена в более знакомую переменную PATH… но вы должны сделать это в переменной PATH, потому что вас могут обмануть, запустив фейковую команду из какого-нибудь скачанного кода.

Моя устанавливается начальной точкой:

CDPATH=.:/space:/etc:/var/lib:/usr/share:/opt

4) SHLVL

Вы когда-нибудь задумывались, ввод exit выведет вас из текущей оболочки bash в другую «родительскую» оболочку или просто полностью закроет окно консоли?

Эта переменная отслеживает, насколько глубоко вы вложены в оболочку bash. Если создать новый терминал, то он установлен на 1:

$ echo $SHLVL
1

Затем, если запустить другой процесс оболочки, число увеличивается:

$ bash
$ echo $SHLVL
2

Это может быть очень полезно в скриптах, где вы не уверены, следует выходить или нет, или отслеживать, где вы находитесь по вложенности.

5) LINENO

Также для анализа текущего состояния и отладки полезна переменная LINENO, которая сообщает количество команд, выполненных в сеансе к настоящему моменту:

$ bash
$ echo $LINENO
1
$ echo $LINENO
2

Это чаще всего используется при отладке скриптов. Вставляя такие строки, как echo DEBUG:$LINENO, вы можете быстро определить, где в скрипте вы находитесь (или нет).

6) REPLY

Если, как я, вы обычно пишете такой код:

$ read input
echo do something with $input

то может стать сюрпризом, что не нужно вообще беспокоиться о создании переменной:

$ read
echo do something with $REPLY

Это делает то же самое.

7) TMOUT

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

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

То есть это альтернатива sleep 1 && exit:

$ TMOUT=1

Переменные Linux | Блог любителя экспериментов

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

Переменные в bash очень интенсивно используются при написании скриптов, как впрочем, и в любом языке программирования для написания программ. Типы переменных в bash отсутствуют. Переменная в bash может представлять собой число, символ или строку символов. Имя переменной может начинаться с буквы или с символа подчеркивания и не может содержать дефис.Физически, переменные представляют собой именованные участки памяти, в которые может быть записана какая-либо информация. Необходимо понимать различия между именем переменной и ее значением. Если var1 — это имя переменной, то $var1 — это ссылка на ее значение.

Хотя, вышесказанное об отсутствии типа переменной можно оспорить, ибо переменные в bash делятся на Ключевые переменные (их же называю еще — глобальными, стандартными, переменные среды или внутренними) и пользовательские (которые определены пользователем во время работы). При этом, пользователь может переводит свою пользовательскую переменную в глобальную, с помощью команды export. Об остальных командах управления переменным можно почитать тут.

При использовании переменных, существует такое негласное соглашение, упрощающее работу: для глобальных переменных используются только ПРОПИСНЫЕ буквы, для остальных — строчные.

Переменные средЫ

Давайте поговорим о переменных среды. Данные переменные, заданы в файлах /etc/.profile, ~/.profile, ~/.bashrc, ~/.bash_profile и инициализируются при загрузке, либо при выполнении команды «. .файл_инициализации«. Обычно, основные значения переменных среды следующие:

$BASH

В переменной $BASH содержится полный путь до исполняемого файла командной оболочки Bash.

$BASH_VERSION

В переменную $BASH_VERSION записывается версия Bash.

$CDPATH

Переменная, которая хранит пути поиска каталога. (используется при вводе команды cd имя_каталога без слэша)

$CLASSPATH

содержит список каталогов для поиска файлов классов Java и архивов Java.

$HOME

домашний каталог текущего пользователя.

$HOSTNAME

В переменной $HOSTNAME хранится имя компьютера.

$HISTSIZE

количество событий, хранимых в истории за 1 сеанс

$HISTFILE

Расположение файла истории событий

$HISTFILESIZE

количество событий, хранимых в истории между сеансами

$IFS

переменная хранит символы, являющиеся разделителями команд и параметров. (по умолчанию — пробел, табуляция и новая строка)

$LANG

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

$MAIL

Место, где храниться почта

$OSTYPE

В переменной $OSTYPE содержится описание операционной системы.

$PATH

список каталогов для поиска команд и приложений, когда полный путь к файлу не задан.

$PS1

PS1 используется как основная строка приглашения. (то самое [root@proxy ~]#)

$PS2

PS2 используется как вторичная строка приглашения.

$PROMPT_COMMAND

Эта команда должна быть выполнена до отображения строки приглашения Bash.

$PWD

полный путь к текущему рабочему каталогу.

$SHELL

полный путь к текущей командной оболочке.

$USER

В переменной $USER содержится имя текущего пользователя.

Переменные пользователя

Присвоение значения переменной

Пользовательские переменные появляются, как только пользователь «объявит» данную переменную, то есть присвоит переменной какое-то значение:

$ var="123   345"       # Присваивание значения переменной
# Если в значениях переменных встречаются пробелы,
# то использование кавычек обязательно, иначе - можно без кавычек. 
$ variable=$var         # Подстановка значения переменной
#-------------------------------------------------------------------------
# Использование пробельных символов
#  с обеих сторон символа "=" присваивания недопустимо.
# Если записать "VARIABLE =value",
#  то интерпретатор попытается выполнить команду "VARIABLE" с параметром "=value".
# Если записать "VARIABLE= value",
#  то интерпретатор попытается установить переменную окружения "VARIABLE" в ""
#  и выполнить команду "value".
#-------------------------------------------------------------------------
$ echo var              # Это НЕ вывод переменной
var
$ echo $var
123 345
$ echo $variable
123 345
$ echo "$variable"
123   345
# Как видно, использование кавычек при выводе значения переменной сохраняет
# пробельные символы в переменной
$ echo '$variable'
$variable
$ echo \$variable
$variable
# Внутри одинарных кавычек не производится подстановка значений переменных,
#  т. е. "$" интерпретируется как простой символ. А так же при использовании
#  символа экранирования.
$ variable=            # Запись пустого значения в переменную(!но не удаление)
$ echo $variable

#  Обратите внимание: запись пустого значения — это не то же самое,
#   что сброс переменной, хотя конечный результат — тот же (см. ниже).
$ echo "uninitialized_variable = $uninitialized_variable"
uninitialized_variable = #пустое
# Неинициализированная переменная содержит "пустое" значение.
$ unset uninitialized_variable    # Сброс переменной.
$ echo "uninitialized_variable = $uninitialized_variable"
uninitialized_variable = #пустое

Действия над переменными

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

$ readonly variable    # пометка переменной "только для чтения"
$ variable=789
-bash: variable: доступная только на чтение переменная
$ cat test             #содержимое первого скрипта
#! /bin/bash
variable1=znachenie    #объявление переменной
echo "test 1: $variable1"      #вывод переменной
. /subtest              #запуск вложенного скрипта
echo "test 2: $variable1"           #вывод переменной после запуска вложенного скрипта
export variable1       #экспорт переменной
echo "test 3: $variable1"
./subtest
echo "test 4: $variable1"
$ cat subtest          #содержимое скрипта, запускаемого из первого
#! /bin/bash
echo "subtest 1: $variable1"
variable1=drugoe
echo "subtest 2: $variable1"
$ ./test               #запуск скрипта
test 1: znachenie
subtest 1:
subtest 2: drugoe
test 2: znachenie
test 3: znachenie
subtest 1: znachenie
subtest 2: drugoe
test 4: znachenie
$ cat where
where=$(pwd)
echo "Вы работаете в каталоге 1: $where"
echo "Вы работаете в каталоге 2: $(pwd)"
where2=`pwd`
echo "Вы работаете в каталоге 3: $where2"
# Как видно, переменной можно присвоить значение вывода какой-либо команды
# используя комбинацию $(command) или `command` (апострофы). 
$ ./where
Вы работаете в каталоге 1:  /home/user
Вы работаете в каталоге 2:  /home/user
Вы работаете в каталоге 3: /home/user

Особые переменные (Позиционные переменные)

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

# Рассмотрим содержимое командного сценария
$ cat display_arg
#! /bin/bash
echo "Имя запущенного сценария: $0"
echo "Первые пять аргументов командной строки: $1 $2 $3 $4 $5"
echo "Всего аргументов сценария: $#"
echo "Все аргументы у запущенного сценария: $*"
echo "Если аргументов более 10, то выводим 10 так: ${10}"
echo "PID запущенного сценария: $$"
sleep 5 &
echo "PID последнего процесса, запущенного в фоне: $!"
ls display_
echo "Команда ls display_ завершилась статусом: $?"
ls display_arg
echo "Команда ls display_arg завершилась статусом: $?"
# Запустим сценарий
$ . /display_arg 1 98 kjk 98 njk88 kjkj 78 kjkj66 jkj k l h
Имя запущенного сценария: ./display_arg
Первые пять аргументов командной строки: 1 98 kjk 98 njk88
Всего аргументов сценария: 12
Все аргументы у запущенного сценария: 1 98 kjk 98 njk88 kjkj 78 kjkj66 jkj k l h
Если аргументов более 10, то выводим 10 так: k
PID запущенного сценария: 3316
PID последнего процесса, запущенного в фоне: 3317
ls: невозможно получить доступ к display_: Нет такого файла или каталога
Команда ls display_ завершилась статусом: 2
display_arg
Команда ls display_arg завершилась статусом: 0
$

Из приведенного скрипта видно, что:

$0

хранит имя команды, запустившей сценарий

$1-$n

переменные хранят 1, 2, 3,…n позицию аргументов команды

$#

хранит количество аргументов команды

$*

хранит значение всех аргументов командной строки через пробел

$@

хранит значение всех аргументов командной строки в виде списка

$$

хранит PID запущенного сценария (процесса)

$!

хранит значение PID последнего процесса, запущенного в фоне

$?

Статус выхода запущенной последней программы. Он так же называется кодом условия, кодом возврата. По соглашению, ненулевое значение статусы завершения соответствует значению false и обозначает неудачное завершение процесса. Код выхода равный 0 соответствует true и обозначает успешное завершение программы. (в нашем примере ls display_ завершилось с ошибкой и кодом выхода 2, т.к. файла или каталога display_ не существует)

Действия над переменными 2

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

$ cat set_shift
#! /bin/bash
echo "var1=$1   var2=$2         var3=$3"
shift
echo "var1=$1   var2=$2         var3=$3"
shift
echo "var1=$1   var2=$2         var3=$3"
shift
echo "var1=$1   var2=$2         var3=$3"

echo "Посмотрим как присваиваются переменные командой set"
set как это присваивается
echo "Вот $1 $3 $2"
$ . /set_shift mama papa dom
var1=mama       var2=papa               var3=dom
var1=papa       var2=dom                var3=
var1=dom        var2=           var3=
var1=   var2=           var3=
Посмотрим как присваиваются переменные командой set
Вот как присваивается это
$

Как видно, команда shift «сдвигает» позиционные параметры, в результате чего параметры «сдвигаются» на одну позицию влево.

X <- $1, $1 <- $2, $2 <- $3, $3 <- $4, и т.д.

Прежний аргумент $1 теряется, но аргумент $0 (имя файла сценария) остается без изменений.

Команда set устанавливает позиционные переменные на основе переданных ей аргументов, разделенных пробелами. Соответственно, команде set возможно передать в виде аргументов и вывод какой-либо команды в виде set $(command). Параметры команды set можно посмотреть тут.

P.S. Забыл указать на такой момент.Кроме использования ссылки на переменную в формате $имя_переменной, возможен и такой синтаксис: ${имя_переменной}. Данный синтаксис позволяет объединить переменную с другим текстом. Пример:

server:~# var10=alex
server:~# echo $var10ander

server:~# echo ${var10}ander
alexander

Как видно в примере, при попытке вывести значение переменной $var10ander выводится пустая строка, и правильно, потому что такой переменной нет. при заключении переменной в фигурные скобки — значение переменной объединяется с последующим текстом.

Резюме

На сегодня это все. Думаю представление о том, как работают переменные в bash, я изложил понятно. Желаю вам побольше практики!

Хочу сказать спасибо товарисчу — начальнику бога http://poplinux.ru/ за некоторые процитированные в статье примеры.

С Уважением, Mc.Sim!

Назначение и варианты использования переменных в скриптах

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

Подстановка переменных

Важно понимать разницу между именем переменной и значением этой переменной, и не забывать о ней. Например: variable — это символическое имя переменной
в то время как $variable — это уже ссылка на значение переменной ( на область памяти, содержащую значение переменной с именем variable ). Имена переменных, без префикса $, могут использоваться в процессе объявления переменной, то есть когда переменной присваивается определенное значение, при удалении значения переменной, при экспорте и в случаях — когда переменная является названием сигнала.
Присвоить значение переменной можно с помощью оператора =:

различными вариантами с использованием оператора read:

или в заголовке цикла:

Если ссылка на переменную, заключена в двойные кавычки, это никак не повлияет на работу подстановки переменной, то есть:

  1. #!/bin/bash
  2.  
  3. var="hello"
  4. echo "$var world"

выведет:

freebsd /# . /test.sh
hello world

если-же строка с переменной заключается в одинарные кавычки, в них экранируются любые служебные символы, то строка будет выведена в том виде, в котором она записана в тесте сценария, без подстановки значения переменной:

  1. #!/bin/bash
  2.  
  3. var="hello"
  4. echo '$var world'

выведет:

freebsd /# ./test.sh
$var world

Форма записи $var, является упрощенным вариантом ${var}. Запись с фигурными скобками ${var}, является более строгим вариантом, ее можно применять там, где обычный вариант вызывает синтаксическую ошибку.

Примеры назначения и подстановки переменных
  1. #!/bin/bash
  2.  
  3. a=375
  4. hello=$a

# Использование пробелов, перед, или после, знака =, не допустимо
# При записи VAR =value, интерпретатор попытается выполнить команду VAR с параметром =value.
# Если попробовать присвоить значение переменной таким образом VAR= value, будет произведена попытка назначить переменной окружения VAR пустое
# значение, после чего, выполнить команду value.

  1. echo hello    # Здесь просто будет выведена строка "hello"
  2.  
  3. echo $hello 
  4. echo ${hello} # Идентично предыдущей строке.
  5.  
  6. echo "$hello"
  7. echo "${hello}"
  8.  
  9. echo

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

  1. #!/bin/sh
  2.  
  3. hello="A B  C   D"
  4. echo $hello   
  5. echo "$hello" 
  6. echo '$hello'
freebsd /# . /test.sh
A B C D
A B  C   D
$hello

Объявление неинициализированной переменной, фактически то-же самое что и сброс переменной

  1. #!/bin/sh
  2.  
  3. # Неинициализированная переменная
  4. var=
  5. echo "var = $var"
  6.  
  7. # Присвоение значения переменной
  8. var=100
  9. echo "var = $var"
  10.  
  11. # Сброс значения переменной
  12. unset var
  13. echo "var = $var"
freebsd /# ./test.sh
var =
var = 100
var =

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

  1. echo "$uninitialized"                                # пустое значение
  2. let "uninitialized += 5"                             # к пустому значению прибавить 5
  3. echo "$uninitialized"                                # результат 5

Допускается присвоение значений нескольким переменным в одной строке.

  1. var1=variable1  var2=variable2  var3=variable3
  2. echo "var1=$var1   var2=$var2  var3=$var3"

Со старыми версиями «sh» могут возникнуть проблемы .

Присваивание значений переменным

Операцией присвоения значения переменной в bash является символ равно, «=», в зависимости от контекста использования так-же является оператором сравнения «равно».

Простое присваивание
  1. #!/bin/bash
  2.  
  3. # Символ  '$' не используется 
  4.  
  5. a=879
  6. echo "Значение переменной \"a\" = $a"
  7.  
  8. # Присваивание значения с помощью ключевого слова 'let'
  9. let a=16+5
  10. echo "Значение переменной \"a\" = $a."
  11.  
  12. # Неявное присваивание в заголовке цикла 'for' 
  13. echo -n "Значения переменной \"a\" в цикле: "
  14. for a in 7 8 9 11
  15. do
  16.   echo -n "$a "
  17. done
  18.  
  19. # Одна из разновидностей присваивания с использованием инструкции 'read' 
  20. echo -n "Введите значение переменной \"a\" "
  21. read a
  22. echo "Значение переменной \"a\" теперь стало равным: $a. "
  23.  
  24. exit 0
Простое и замаскированное присваивание
  1. #!/bin/bash
  2.  
  3. a=23
  4. echo $a
  5. b=$a
  6. echo $b

# Подстановка команд, немного более сложный вариант.

  1. a=`echo Hello!`   # Переменной 'a' присваивается результат выполнения команды 'echo'
  2. echo $a

Обратите внимание на восклицательный знак (!) в подстанавливаемой команде, из командной строки такой вариант работать не будет, поскольку здесь используется механизм истории команд bash. Но в сценариях использование истории команд запрещено

  1. a=`ls -l`         # Переменной 'a' присваивается результат выполнения команды 'ls -l'
  2. echo $a           # Если не используются кавычки, будут удалены лишние пробелы и пустые строки
  3. echo
  4. echo "$a"         # При использовании кавычек, все пробелы и пустые строки будут сохранены
  5.  
  6. exit 0

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

  1. #!/bin/sh
  2.  
  3. R=$(uname)
  4. echo $R
f
reebsd /# ./test.sh
FreeBSD

Переменные Bash не имеют определенного типа

В отличие от большинства других языков программирования, Bash не разделяет переменные по типам. По сути, переменные Bash являются строковыми переменными, но, в зависимости от контекста, Bash допускает целочисленную арифметику с переменными. Определяющим фактором здесь служит содержимое переменных.

Целое число или строка
  1. #!/bin/bash
  2.  
  3. # Переменной присваивается целое число
  4. a=2334
  5. let "a += 1"
  6. echo "a = $a "
  7. # Переменная все еще является целым числом 2335
  8.  
  9. # Замена "23" на "BB"
  10. b=${a/23/BB}
  11.  
  12. # Происходит трансформация числа в строку. 
  13. echo "b = $b"            # b = BB35
  14. declare -i b             # Явное указание типа ничего не изменит
  15. echo "b = $b"            # b = BB35
  16.  
  17. let "b += 1"             # BB35 + 1 =
  18. echo "b = $b"            # b = 1
  19.  
  20. c=BB34
  21. echo "c = $c"            # c = BB34
  22. d=${c/BB/23}             # замена "BB" на "23".
  23.  
  24. # Переменная $d становится целочисленной.
  25. echo "d = $d"            # d = 2334
  26. let "d += 1"             # 2334 + 1 =
  27. echo "d = $d"            # d = 2335
  28.  
  29. # Как ведут себя  "пустые" переменные
  30. e=""
  31. echo "e = $e"            # e =
  32. let "e += 1"             # В арифметических операциях возможно использование "пустых" переменных
  33. echo "e = $e"            # e = 1
  34. # "Пустая" переменная становится целочисленной. 
  35.  
  36. # Поведение неинициализированных переменных
  37. echo "f = $f"            # f =
  38. let "f += 1"             # Арифметические операции разрешены
  39. echo "f = $f"            # f = 1
  40. echo                     # Неинициализированная переменная трансформируется в целочисленную.

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

Специальные типы переменных

локальные переменные

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

  1. #!/usr/local/bin/bash
  2.  
  3. a=111
  4. { a=555; }
  5. echo "a = $a"
freebsd /# ./test1.sh
a = 555
переменные окружения

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

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

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

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

 freebsd /# eval "`seq 10000 | sed -e 's/.*/export var&=ZZZZZZZZZZZZZZ/'`"
freebsd /# bash$ du
freebsd /# /usr/bin/du: Argument list too long

Если сценарий меняет переменные окружения, они должны быть экспортированы, т.е передаться окружению, локальному по отношению к сценарию. Делается это с помощью команды export.

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

Позиционные параметры

Позиционные параметры, это аргументы, получаемые сценарием при запуске из командной строки — $0, $1, $2, $3…, где $0 — это название файла сценария, $1 — первый аргумент, $2 — второй, $3 — третий и так далее. Аргументы, следующие за $9, должны быть заключены в фигурные скобки, например: ${10}, ${11}, ${12}.

Специальные переменные $* и $@ содержат все поступившие в сценарий позиционные параметры.

  1. #!/bin/bash
  2.  
  3. # Данный сценарий должен вызываться как минимум с 10 аргументами
  4. # ./scriptname 1 2 3 4 5 6 7 8 9 10
  5. MINPARAMS=10
  6.  
  7. echo
  8.  
  9. echo "Имя сценария: \"$0\"."
  10. # Для текущего каталога добавит ./
  11. echo "Имя файла сценария: \"`basename $0`\"."
  12. # Добавит путь к имени файла (см. 'basename')
  13.  
  14. echo
  15.  
  16. if [ -n "$1" ]              # Проверяемая переменная заключена в двойные кавычки.
  17. then
  18.  echo "Параметр #1: $1"     # здесь кавычки для нужны для экранирования символа #
  19. fi
  20.  
  21. if [ -n "$2" ]
  22. then
  23.  echo "Параметр #2: $2"
  24. fi
  25.  
  26. if [ -n "$3" ]
  27. then
  28.  echo "Параметр #3: $3"
  29. fi
  30.  
  31. # . ..
  32.  
  33. if [ -n "${10}" ]  # Параметры, следующие за $9 должны заключаться в фигурные скобки
  34. then
  35.  echo "Параметр #10: ${10}"
  36. fi
  37.  
  38. echo "-----------------------------------"
  39. echo "Все аргументы командной строки: "$*""
  40.  
  41. if [ $# -lt "$MINPARAMS" ]
  42. then
  43.   echo
  44.   echo "Количество аргументов командной строки должно быть не менее $MINPARAMS !"
  45. fi
  46.  
  47. echo
  48.  
  49. exit 0

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

  1. args=$#           # Количество переданных аргументов.
  2. lastarg=${!args}  # Обратите внимание: lastarg=${!$#} неприменимо. 

Сценарий может вести себя по разному в зависимости от имени сценария. Для этого сценарий должен проанализировать аргумент $0 — имя файла сценария. Это могут быть и имена символических ссылок на файл сценария.

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

  1. variable1_=$1_ 
  2. # Это предотвратит появление ошибок, даже при отсутствии входного аргумента.
  3.  
  4. critical_argument01=$variable1_
  5.  
  6. # Дополнительные символы всегда можно "убрать" позднее.
  7. # Это может быть сделано примерно так:
  8. variable1=${variable1_/_/}   # Побочный эффект возникает только если имя переменной $variable1_ будет начинаться с символа "_". 
  9. # Здесь используется один из вариантов подстановки параметров. Отсутствие шаблона замены приводит к удалению.
  10.  
  11. # Более простой способ заключается в обычной проверке передаваемых аргументов.
  12. if [ -z $1 ]
  13. then
  14.   exit $POS_PARAMS_MISSING
  15. fi

Сценарий использующий программу whois для определения имени домена

  1. #!/bin/bash
  2.  
  3. # Команда 'whois domain-name' определяет имя домена на одном из 3 серверов:
  4. #                    ripe.net, cw.net, radb.net
  5.  
  6. # Разместите этот скрипт под именем 'wh' в каталоге /usr/local/bin
  7.  
  8. # Требуемые символические ссылки:
  9. # ln -s /usr/local/bin/wh /usr/local/bin/wh-ripe
  10. # ln -s /usr/local/bin/wh /usr/local/bin/wh-cw
  11. # ln -s /usr/local/bin/wh /usr/local/bin/wh-radb
  12.  
  13. if [ -z "$1" ]
  14. then
  15.   echo "Использование: `basename $0` [domain-name]"
  16.   exit 65
  17. fi
  18.  
  19. case `basename $0` in
  20. # Проверка имени скрипта и, соответственно, имени сервера
  21.     "wh"     ) whois $1@whois. ripe.net;;
  22.     "wh-ripe") whois [email protected];;
  23.     "wh-radb") whois [email protected];;
  24.     "wh-cw"  ) whois [email protected];;
  25.     *        ) echo "Использования: `basename $0` [domain-name]";;
  26. esac
  27.  
  28. exit 0

Команда shift сдвигает позиционные параметры удаляя первый из них.

$1 <— $2, $2 <— $3, $3 <— $4, и т.д.

При этом аргумент $0 (имя сценария) остается без изменений. Если вашему сценарию передается большое количество аргументов из командной строки, команда shift позволяет получить доступ к аргументам, с порядковым номером больше 9, без использования фигурных скобок.

Использование команды shift

В данном случае команда ‘shift используется для перебора всех аргументов командной строки.

  1. #!/bin/bash
  2.  
  3. until [ -z "$1" ]  # Пока все параметры не будут разобраны
  4. do
  5.   echo -n "$1 "
  6.   shift
  7. done
  8.  
  9. echo              
  10.  
  11. exit 0

Так-же, команда shift, может применяться и к входным аргументам функций.

freebsd /# ./test1.sh 1 2 3 a b c
1 2 3 a b c

Переменные в Bash

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

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

Как они работают?

Переменная является временным хранилищем для части информации.  Для переменных можно выполнить два действия:

  • Установка значения для переменной.
  • Чтение значения переменной.

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

Чтобы прочитать переменную, мы помещаем ее имя (которому предшествует знак $) в любом месте сценария, который нам нужен. Прежде чем Bash интерпретирует (или запускает) каждую строку нашего скрипта, он сначала проверяет, имеются ли какие-либо имена переменных. Для каждой переменной, которую она идентифицировала, она заменяет имя переменной своим значением. Затем он запускает эту строку кода и снова запускает процесс на следующей строке.

Вот несколько быстрых точек синтаксиса. Они будут подробно рассмотрены и продемонстрированы ниже.

  • При указании или чтении переменной мы помещаем знак $ перед именем переменной.
  • При установке переменной мы оставляем знак $.
  • Некоторым людям нравится писать имена переменных в верхнем регистре, чтобы они выделялись. Это ваше предпочтение. Они могут быть все прописными буквами, все строчными буквами или смесью.
  • Переменная может быть размещена в любом месте сценария (или в командной строке, если на то пошло), а при запуске Bash заменит его значением переменной. Это стало возможным, поскольку замена выполняется до запуска команды.

Аргументы командной строки

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

Когда мы запускаем программу в командной строке, вы будете знакомы с предоставлением аргументов после нее, чтобы контролировать ее поведение. Например , мы могли бы выполнить команду Ls -l / и т.д. . -l и / etc — оба аргумента командной строки для команды ls . Мы можем сделать подобное с нашими сценариями bash. Для этого мы используем переменные $ 1 для представления первого аргумента командной строки, $ 2 для представления второго аргумента командной строки и т. д. Они автоматически устанавливаются системой, когда мы запускаем наш скрипт, поэтому все, что нам нужно сделать, это обратиться к ним.

Давайте посмотрим на пример mycopy.sh

#!/bin/bash
# Простой сценарий копирования

cp $1 $2

# Давайте проверим, что копия работала

echo Details for $2
ls -lh $2

#!/bin/bash

# Простой сценарий копирования

 

cp $1 $2

 

# Давайте проверим, что копия работала

 

echo Details for $2

ls -lh $2

Давайте разберем это:

  • Строка 4 — запустите команду cp с первым аргументом командной строки в качестве источника и второго аргумента командной строки в качестве адресата.
  • Строка 8 — запуск эха команды для печати сообщения.
  • Строка 9 — После завершения копирования запустите команду ls для адресата, чтобы убедиться, что она сработала.  Мы включили опции l, чтобы показать нам дополнительную информацию и h, чтобы сделать размер читаемым человеком, чтобы мы могли проверить его правильность копирования.

Мы обсудим их использование немного больше в следующей статье.

Другие специальные переменные

Есть несколько других переменных, которые система устанавливает и для вас.

  • $0 — имя скрипта Bash.
  • $1-$9 — Первые 9 аргументов для скрипта Bash. (Как уже упоминалось выше.)
  • $# — Сколько аргументов было передано скрипту Bash.
  • $@ — Все аргументы, предоставленные сценарию Bash.
  • $?— Статус выхода последнего процесса.
  • $$ — Идентификатор процесса текущего скрипта.
  • $USER — имя пользователя, выполняющего скрипт.
  • $HOSTNAME — имя хоста, на котором запущен скрипт.
  • $SECONDS — количество секунд с момента запуска скрипта.
  • $RANDOM — Возвращает другое случайное число каждый раз, когда он упоминается.
  • $LINENO — возвращает текущий номер строки в сценарии Bash.

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

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

Настройка собственных переменных

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

Существует несколько способов, которыми могут быть заданы переменные (например, часть выполнения команды), но базовая форма следует этому шаблону:

переменная = значение

Это одна из тех областей, где важно форматирование. Обратите внимание, что по обе стороны от знака равенства (=) нет места.  Мы также оставляем знак $ с начала имени переменной при настройке.

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

Вот простой пример, иллюстрирующий их использование.

#!/bin/bash
# Пример простой переменной

myvariable=Hello

anothervar=Fred

echo $myvariable $anothervar
echo

sampledir=/etc

ls $sampledir

#!/bin/bash

# Пример простой переменной

 

myvariable=Hello

 

anothervar=Fred

 

echo $myvariable $anothervar

echo

 

sampledir=/etc

 

ls $sampledir

Давайте разберем это:

  • Строки 4 и 6 — задайте значение двух переменных myvariable и anothervar.
  • Строка 8 — запустить эхо команды, чтобы проверить, что переменные были установлены в соответствии с назначением.
  • Строка 9 — запустите команду echo на этот раз без аргументов. Это хороший способ получить пустую строку на экране, чтобы помочь решить проблему.
  • Строка 11 — установите другую переменную, на этот раз в качестве пути к определенному каталогу.
  • Строка 13 — запустите команду ls, заменив значение переменной sampledir в качестве первого аргумента командной строки.

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

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

Цитаты

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

  • Помните, что команды работают точно так же в командной строке, как и в скрипте.

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

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

  • Одиночные кавычки будут обрабатывать каждый символ буквально.
  • Двойные кавычки позволят вам выполнять подстановку (то есть включают переменные в пределах значения).

Замена команды

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

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

Давайте разберем это:

  • Строка 1 — Запустим команду ls . Обычно его выход будет состоять из нескольких строк.  Я немного сократил его в приведенном выше примере, чтобы сэкономить место.
  • Строка 4 — Когда мы сохраняем команду переменной myvar, все строки новой строки удаляются , а вывод теперь находится в одной строке.

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

Экспорт переменных

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

script1.sh

#!/bin/bash
# demonstrate variable scope 1.

var1=blah
var2=foo

# Let’s verify their current value

echo $0 :: var1 : $var1, var2 : $var2

export var1
./script2.sh

# Let’s see what they are now

echo $0 :: var1 : $var1, var2 : $var2

#!/bin/bash

# demonstrate variable scope 1.

 

var1=blah

var2=foo

 

# Let’s verify their current value

 

echo $0 :: var1 : $var1, var2 : $var2

 

export var1

./script2.sh

 

# Let’s see what they are now

 

echo $0 :: var1 : $var1, var2 : $var2

script2.sh

#!/bin/bash
# demonstrate variable scope 2

# Let’s verify their current value

echo $0 :: var1 : $var1, var2 : $var2

# Let’s change their values

var1=flop
var2=bleh

#!/bin/bash

# demonstrate variable scope 2

 

# Let’s verify their current value

 

echo $0 :: var1 : $var1, var2 : $var2

 

# Let’s change their values

 

var1=flop

var2=bleh

Теперь давайте запустим его и посмотрим, что произойдет.

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

Экспорт переменных — односторонний процесс. Первоначальный процесс может передавать переменные новому процессу, но все, что происходит с копией переменных, не влияет на исходные переменные.

Экспорт переменных — это то, что вам, вероятно, не нужно будет беспокоиться о большинстве сценариев Bash, которые вы создадите. Иногда вы можете захотеть разбить конкретную задачу на несколько отдельных сценариев, однако упростить управление или разрешить повторное использование (что всегда хорошо). Например, вы можете создать сценарий, в котором будет скопирована копия всех файлов, экспортированных на определенную переменную, датированной (то есть сегодняшней датой, предшествующей имени файла).  Затем вы можете легко вызвать этот скрипт из других сценариев, которые вы создаете, всякий раз, когда вы хотите сделать снимок набора файлов.

Часть 1. Что такое скрипт Bash?

Часть 3. Пользовательский ввод в Bash

Источник: https://ryanstutorials.net/bash-scripting-tutorial/bash-variables.php

Пользовательский ввод в Bash

Если мы хотим попросить пользователя ввести его, мы будем использовать команду read . Эта команда берет ввод и сохраняет его в переменной.

Давайте рассмотрим простой пример:

introduction.sh

#!/bin/bash
# Ask the user for their name

echo Hello, who am I talking to?

read varname

echo It\’s nice to meet you $varname

#!/bin/bash

# Ask the user for their name

 

echo Hello, who am I talking to?

 

read varname

 

echo It\’s nice to meet you $varname

Давайте разберем это:

  • Строка 4 — Распечатайте сообщение, запрашивающее пользователя для ввода.
  • Строка 6 — Запустите команду чтения и сохраните ответ пользователя в переменной varname
  • Строка 8 — echo еще одно сообщение, чтобы проверить, что команда чтения выполнена. Примечание. Мне пришлось поставить обратную косую черту (\) перед «так, чтобы она была экранирована.
  • Примечание. Райан выше выделен курсивом, чтобы показать, что это то, что я набрал. На вашем терминальном входе будет нормально отображаться.

Больше с чтением

Вы можете изменить поведение чтения с помощью различных параметров командной строки. (См. Страницу руководства для чтения, чтобы увидеть все из них.) Однако два часто используемых варианта — это -p, который позволяет вам указать подсказку и -s, что делает ввод тихим. Это может упростить запрос комбинации имени пользователя и пароля, как показано ниже:
login.sh

#!/bin/bash
# Ask the user for login details

read -p ‘Username: ‘ uservar
read -sp ‘Password: ‘ passvar
echo
echo Thankyou $uservar we now have your login details

#!/bin/bash

# Ask the user for login details

 

read -p ‘Username: ‘ uservar

read -sp ‘Password: ‘ passvar

echo

echo Thankyou $uservar we now have your login details

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

Больше переменных

До сих пор мы рассматривали одно слово как вход. Однако мы можем сделать больше, чем это.

cars.sh

#!/bin/bash
# Demonstrate how read actually works

echo What cars do you like?

read car1 car2 car3

echo Your first car was: $car1
echo Your second car was: $car2
echo Your third car was: $car3

#!/bin/bash

# Demonstrate how read actually works

 

echo What cars do you like?

 

read car1 car2 car3

 

echo Your first car was: $car1

echo Your second car was: $car2

echo Your third car was: $car3

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

Чтение из STDIN

Это общепринятое в Linux для труб серии простой, одной цели команды вместе , чтобы создать большее решение , отвечающее наши точные потребности. Способность делать это — одна из реальных задач Linux. Оказывается, мы можем легко разместить этот механизм и с нашими скриптами. Поступая таким образом, мы можем создавать скрипты, которые действуют как фильтры для изменения данных по определенным для нас способам.

Баш вмещает трубопроводы и перенаправление посредством специальных файлов. Каждый процесс получает собственный набор файлов (один для STDIN, STDOUT и STDERR соответственно), и они связаны при вызове или перенаправлении.  Каждый процесс получает следующие файлы:

  • STDIN — /proc/<processID>/fd/0
  • STDOUT — /proc/<processID>/fd/1
  • STDERR — /proc/<processID>/fd/2

Чтобы сделать жизнь более удобной, система создает для нас несколько ярлыков:

  • STDIN — /dev/stdin or /proc/self/fd/0
  • STDOUT — /dev/stdout or /proc/self/fd/1
  • STDERR — /dev/stderr or /proc/self/fd/2

fd в дорожках выше обозначает дескриптор файла.

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

summary

#!/bin/bash
# Основное резюме моего отчета о продажах

echo Here is a summary of the sales data:
echo ====================================
echo

cat /dev/stdin | cut -d’ ‘ -f 2,3 | sort

#!/bin/bash

# Основное резюме моего отчета о продажах

 

echo Here is a summary of the sales data:

echo ====================================

echo

 

cat /dev/stdin | cut -d’ ‘ -f 2,3 | sort

Давайте разберем это:

  • Строки 4, 5, 6 — Распечатайте заголовок для вывода
  • Строка 8 — cat файл, представляющий STDIN, вырезает установку разделителя на пробел, поля 2 и 3 затем сортируют вывод.

Так что я должен использовать?

Итак, теперь у нас есть 3 метода ввода данных от пользователя:

  • Аргументы командной строки
  • Чтение ввода во время выполнения скрипта
  • Принять данные, которые были перенаправлены в скрипт Bash через STDIN

Какой метод лучше всего зависит от ситуации.

Как правило, вы предпочитаете аргументы командной строки. Они наиболее удобны для пользователей, поскольку данные будут храниться в истории команд, чтобы они могли легко вернуться к нему. Это также лучший подход, если ваш скрипт может быть вызван другими скриптами или процессами (например, возможно, вы хотите, чтобы он периодически запускался с использованием CRON).

Иногда характер данных таков, что было бы не идеально для его хранения в истории команд людей и т. д. Хорошим примером этого являются учетные данные для входа (имя пользователя и пароль). В этих обстоятельствах лучше всего читать данные во время выполнения скрипта.

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

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

Ультимативно вы должны думать о 3 факторах при принятии решения о том, как пользователи будут предоставлять данные вашему сценарию Bash:

  • Простота использования — какой из этих методов облегчит пользователям использование моего сценария?
  • Безопасность. Есть ли конфиденциальные данные, которые я должен обрабатывать надлежащим образом?
  • Надежность.  Могу ли я сделать так, чтобы моя работа скриптов была интуитивно понятной и гибкой, а также усложнять ошибки?

Часть 2. Переменные в Bash

Часть 4. Сложение, вычитание, умножение, деление, модуль в Bash

Источник: https://ryanstutorials.net/bash-scripting-tutorial/bash-input.php

Встроенные в bash переменные – Блог админа

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

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

echo $ SHELL

  чтобы получить текущую оболочку.

$SHELL – выводит какая оболочка запущена сейчас

$HISTSIZE – выводит размер количества команд, которые могут быть размещены в файле истории

$HISTFILE – выводит где расположен файл истории

$USER – отображает имя пользователя

$EUID – отображает UserID.

$GROUPS – выводит информации о GID.

$PWD – отображает текущую директорию.

$HOSTNAME – отображает имя хоста.

$HOME – выводит вашу домашнюю директорию.

$HOSTTYPE или $MACHTYPE – выводит архитектуру хоста, например 32bit или 64 bit.

$OSTYPE –определяет ОС, например — gnu Linux, sun sol и т.д. Удобно для контроля в какой среде запускается скрипт оболочки.

$TERM –выдает имя терминала.

$TMOUT – выход из оболочки если нет активности на терминале, полезно для безопасности сервера.

$PATH – выводит путь ко всем двоичным файлам, т.е. командам

$PIPESTATUS – для получения статуса вывода канала.

$BASH_VERSION – выводит версию bash. Удобно для контроля в какой среде запускается скрипт оболочки.

$PPID – выводит ID родительского процесса.

$PS1, $PS2, $PS3, $PS4 – различные подсказки. Они полезны для сценариев, управляемых меню.

В скриптах

$RANDOM – выдает случайное число, очень удобно для создания паролей новым пользователям.

$LINENO – Выдает номер строки на которой работает скрипт. Удобно для отладки.

$REPLY – содержит последнее значение чтения.

$SECONDS – выдает количество секунд которые скрипт запущен.

Позиционные параметры: $1, $2, $3, $4, $5, $6, $7, $8, $9

$0 – выдает имя скрипта

$* – все позиционные параметры

$@ – все позиционные параметры через пробел

$# – количество параметров

$$ – ID текущего процесса

$! – ID фонового задания

$? – ошибка или статус выхода

$_ – выдает последний аргумент предыдущей команды

переменных Bash — Bash — W3cubDocs

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

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

БАШ

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

БАШОПЦ

Список включенных параметров оболочки, разделенных двоеточиями.Каждое слово в списке является допустимым аргументом для параметра -s встроенной команды shopt (см. Встроенная команда Shopt). Опции, появляющиеся в BASHOPTS , обозначены как « на » « shopt ». Если эта переменная находится в среде при запуске Bash, каждый параметр оболочки в списке будет включен перед чтением любых файлов запуска. Эта переменная доступна только для чтения.

БАШПИД

Заменяется на идентификатор текущего процесса Bash.Это отличается от $$ при определенных обстоятельствах, таких как подоболочки, которые не требуют повторной инициализации Bash. Присвоение БАШПИД не действует. Если BASHPID не установлен, он теряет свои особые свойства, даже если впоследствии будет сброшен.

ИЛИ БАШИ

Переменная ассоциативного массива, элементы которой соответствуют внутреннему списку псевдонимов, поддерживаемому встроенной функцией alias . (см. Встроенные оболочки Bourne).Элементы, добавленные в этот массив, появятся в списке псевдонимов; однако сброс элементов массива в настоящее время не приводит к удалению псевдонимов из списка псевдонимов. Если BASH_ALIASES не задан, он теряет свои особые свойства, даже если впоследствии сбрасывается.

БАШ_АРГК

Переменная массива, значения которой представляют собой количество параметров в каждом кадре текущего стека вызовов выполнения bash. Количество параметров текущей подпрограммы (функции оболочки или сценария, выполняемого с . или источник ) находится наверху стека. Когда подпрограмма выполняется, количество переданных параметров помещается в BASH_ARGC . Оболочка устанавливает BASH_ARGC только в режиме расширенной отладки (описание опции extdebug для встроенной функции shopt см. В The Shopt Builtin). Установка extdebug после того, как оболочка начала выполнять сценарий, или ссылка на эту переменную, когда extdebug не установлена, может привести к несогласованным значениям.

БАШ_АРГВ

Переменная массива, содержащая все параметры в текущем стеке вызовов выполнения bash. Последний параметр последнего вызова подпрограммы находится наверху стека; первый параметр первоначального вызова находится внизу. При выполнении подпрограммы предоставленные параметры помещаются в BASH_ARGV . Оболочка устанавливает BASH_ARGV только в режиме расширенной отладки (см. Описание встроенной функции extdebug в встроенной программе Shopt ). Установка extdebug после того, как оболочка начала выполнять сценарий, или ссылка на эту переменную, когда extdebug не установлена, может привести к несогласованным значениям.

БАШ_АРГВ0

При ссылке эта переменная расширяется до имени оболочки или сценария оболочки (идентично $ 0 ; см. «Специальные параметры» для описания специального параметра 0). Присвоение BASH_ARGV0 приводит к тому, что присвоенное значение также присваивается $ 0 .Если BASH_ARGV0 не задан, он теряет свои особые свойства, даже если впоследствии сбрасывается.

БАШ_ЦМДС

Переменная ассоциативного массива, элементы которой соответствуют внутренней хэш-таблице команд, поддерживаемой встроенным хеш-кодом (см. Встроенные функции Bourne Shell). Элементы, добавленные в этот массив, появляются в хэш-таблице; однако удаление элементов массива в настоящее время не приводит к удалению имен команд из хеш-таблицы. Если BASH_CMDS не установлен, он теряет свои особые свойства, даже если впоследствии будет сброшен.

BASH_COMMAND

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

БАШ_КОМПАТ

Значение используется для установки уровня совместимости оболочки.См. «Встроенный магазин» для описания различных уровней совместимости и их эффектов. Значение может быть десятичным числом (например, 4,2) или целым числом (например, 42), соответствующим желаемому уровню совместимости. Если BASH_COMPAT не задан или установлен в пустую строку, устанавливается уровень совместимости по умолчанию для текущей версии. Если для BASH_COMPAT установлено значение, не являющееся одним из допустимых уровней совместимости, оболочка выводит сообщение об ошибке и устанавливает уровень совместимости по умолчанию для текущей версии. Допустимые уровни совместимости соответствуют параметрам совместимости, принятым встроенной функцией shopt , описанной выше (например, compat42 означает, что допустимые значения 4.2 и 42). Текущая версия также является допустимым значением.

БАШ_ЭНВ

Если эта переменная установлена, когда Bash вызывается для выполнения сценария оболочки, ее значение раскрывается и используется в качестве имени файла запуска для чтения перед выполнением сценария. См. Bash Startup Fi

Linux с помощью переменной среды Examplesexport из сценария bash

1 февраля 2011 г. mysurface Отправлено в Bash, источник | Просмотров: 201799 | 14 Комментарии »

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

Например, у вас есть env.sh, который содержит некоторые переменные среды

  экспорт HELLO = привет
экспорт HELLO2 = мир  

И вы пытаетесь выполнить env.sh, а затем пытаетесь повторить $ HELLO $ HELLO2 в своей оболочке, вы ничего не получите.

Правильный способ экспортировать переменную среды из сценария в оболочку — использовать источник команд.

  исходный env.sh
echo $ HELLO $ HELLO2
$ привет мир  

Можешь поставить env.sh в / usr / bin, и вы можете сделать исходный код env.sh в любом месте, и он все равно будет работать. Просто вы должны научить своих пользователей использовать исходный код вместо прямого выполнения скрипта. Но я понял, что не многие пользователи знают исходную команду.

В мире Linux всегда есть альтернативный способ сделать то же самое. Вы можете создать новый сеанс bash из своего сценария bash и оставить его там до тех пор, пока пользователь не введет «exit». Bash поддерживает для этого интерактивную опцию.

  баш -и  

Хорошо, как это использовать?

Позвольте мне привести случай и объяснить, почему я хочу использовать bash -i вместо source.

Как программист встроенного Linux, иногда мне может потребоваться скомпилировать некоторые приложения, используя другой набор инструментов, основанный на архитектуре процессора встроенного устройства. Общие переменные среды для инструментальной цепочки — ARCH и CROSS_COMPILE. Кроме того, я также хочу напомнить пользователю, что эта конкретная оболочка предназначена для создания приложений для встроенных устройств, поэтому я хотел бы изменить цвет и формат существующего приглашения bash, которое я могу использовать с переменной PS1.

build_arm.sh

  #! / Bin / bash
экспорт ARCH = рука
экспорт CROSS_COMPILE = arm-none-linux-gnueabi-
экспорт PS1 = "\ e [31mBUILD_ARM \ w \ e [m \ n \ $"

баш -i
  

При выполнении build_arm. sh приглашение bash станет красным, а переменная среды для ARCH и CROSS_COMPILE будет установлена, пока пользователь не наберет «exit», все вернется к нормальному состоянию. Зачем? потому что bash -i интерактивно ожидает ввода пользователя.

  ./build_arm.sh
BUILD_ARM ~
$
    

Еще подсказки для PS1? проверить это Анджелина Джоли.

Примеры ассоциативных массивов

Bash — Блог Энди Валаама

Краткое руководство по использованию ассоциативных массивов в bash. Примечание: только bash версии 4.

Играй в мою игру для Android: Побег кролика!

Обновление: см. Также Bash Arrays.

Основы

$ declare -A MYMAP # Создать ассоциативный массив
$ MYMAP [foo] = bar # Поместите значение в ассоциативный массив
$ echo $ {MYMAP [foo]} # Получить значение из ассоциативного массива
бар
$ echo MYMAP [foo] # НЕПРАВИЛЬНО
МОЯ КАРТА [foo]
$ echo $ MYMAP [foo] # НЕПРАВИЛЬНО
[foo]
 

Создание

$ declare -A MYMAP # Явно объявить
$ MYMAP [foo] = bar # Или эта строка неявно делает ее ассоциативным массивом (в глобальной области видимости bash 4. Только 2+)
$ MYMAP [baz] = quux # Можно добавлять несколько значений одно за другим
$ MYMAP [corge] = grault
 
$ declare -A MYMAP = ([foo] = bar [baz] = quux [corge] = grault) # Инициализировать все сразу
$ echo $ {МОЯ КАРТА [foo]}
бар
$ echo $ {MYMAP [baz]}
quux
 
$ declare -A MYMAP # Или объявить отдельно
$ MYMAP = ([foo] = bar [baz] = quux [corge] = grault) # Затем инициализируйте
$ echo $ {МОЯ КАРТА [foo]}
бар
$ echo $ {MYMAP [baz]}
quux
 

Переменные как ключи

$ K = баз
$ MYMAP [$ K] = quux # Использовать переменную как ключ для помещения значения в ассоциативный массив
$ echo $ {MYMAP [$ K]} # Использование переменной в качестве ключа для извлечения значения из ассоциативного массива
quux
$ echo $ {MYMAP [baz]} # Очевидно, что значение доступно через буквальный ключ
quux
 

Цитирование ключей

$ declare -A MYMAP
$ MYMAP [foo A] = "bar B" # Цитирование ключей не имеет значения
$ MYMAP ["corge X"] = "grault Y" # Цитирование ключей не имеет значения
$ echo $ {MYMAP ["corge X"]} # Вы можете получить доступ, цитируя
Grault Y
$ echo $ {MYMAP [corge X]} # Или не беспокойтесь
Grault Y
$ echo $ {МОЯ КАРТА [foo A]}
бар B

$ MYMAP ['waldo 1'] = "fred 2" # Одиночные кавычки также не имеют значения
$ echo $ {МОЯ КАРТА ['waldo 1']}
фред 2
$ echo $ {МОЯ КАРТА [waldo 1]}
фред 2

$ K = плуг
$ MYMAP ['$ K'] = xyzzy # Как обычно, расширение переменных предотвращается за исключением одинарных кавычек
$ echo $ {MYMAP [plugh]}

$ echo $ {МОЯ КАРТА ['$ K']}
xyzzy
 

Отсутствующие ключи

$ MYMAP [foo] = bar
$ echo $ {MYMAP [missing]} # Доступ к отсутствующему значению дает ""

$ # Проверка, отсутствует ли значение в ассоциативном массиве
$ если [$ {MYMAP [foo] + _}]; затем эхо «Найдено»; иначе echo «Не найдено»; фи
Найденный
$ if [$ {MYMAP [отсутствует] + _}]; затем эхо «Найдено»; иначе echo «Не найдено»; фи
Не найдено
 

Петли

$ declare -A MYMAP = ([foo a] = bar [baz b] = quux)
$ echo "$ {! MYMAP [@]}" # Распечатать все ключи - в кавычках, но кавычки удаляются эхо
foo a baz b

$ # Перебрать все ключи в ассоциативном массиве
$ для K в "$ {! MYMAP [@]}"; сделать echo $ K; сделанный
foo a
baz b

$ для K в $ {! MYMAP [@]}; сделать echo $ K; сделано # НЕПРАВИЛЬНО
фу
а
баз
б

$ # Цикл по ключам и значениям в ассоциативном массиве
$ для K в "$ {! MYMAP [@]}"; сделать echo $ K --- $ {MYMAP [$ K]}; сделанный
foo a --- bar
baz b --- quux

$ # Перебрать все значения в ассоциативном массиве
$ вместо V в "$ {MYMAP [@]}"; сделать echo $ V; сделанный
бар
quux
 

Расчистка

$ declare -A MYMAP
$ MYMAP [foo] = bar
$ echo $ {МОЯ КАРТА [foo]}
бар
$ declare -A MYMAP # Повторное объявление НЕ очищает ассоциативный массив
$ echo $ {МОЯ КАРТА [foo]}
бар
$ unset MYMAP # Чтобы получить очищенный ассоциативный массив, вам необходимо отключить и повторно объявить
$ declare -A MYMAP
$ echo $ {МОЯ КАРТА [foo]}

 

Удаление ключей

$ MYMAP [foo] = bar
$ echo $ {МОЯ КАРТА [foo]}
бар
$ unset $ {MYMAP [foo]} # НЕПРАВИЛЬНО
$ echo $ {МОЯ КАРТА [foo]}
бар
$ unset MYMAP [foo] # Чтобы удалить из ассоциативного массива, используйте "unset" с синтаксисом, аналогичным назначению
$ # НО см.  Следующий раздел, если ключ содержит пробелы
$ echo $ {МОЯ КАРТА [foo]}

$ MYMAP [baz] = quux
$ echo $ {MYMAP [baz]}
quux
$ K = баз
$ unset MYMAP [$ K] # Также можно отключить, используя переменную для ключа
$ # НО см. Следующий раздел, если переменная может содержать пробелы - всегда лучше цитировать
$ echo $ {MYMAP [baz]}

 

Удаление ключей, содержащих пробелы

$ declare -A MYMAP
$ MYMAP [foo Z] = бар
$ echo $ {MYMAP [foo Z]}
бар
$ unset MYMAP [foo Z] # НЕПРАВИЛЬНО
bash: unset: `MYMAP [foo ': неверный идентификатор
bash: unset: `Z] ': неверный идентификатор
$ unset MYMAP ["foo Z"] # Вы должны заключать в кавычки ключи, содержащие пробелы, когда вы unset в ассоциативном массиве
$ echo $ {MYMAP [foo Z]}

$ MYMAP [foo Z] = бар
$ unset MYMAP ['foo Z'] # Одинарные кавычки тоже работают
$ echo $ {MYMAP [foo Z]}

$ MYMAP [baz A] = quux
$ echo $ {MYMAP [baz A]}
quux
$ K = "баз А"
$ unset MYMAP [$ K] # НЕПРАВИЛЬНО
bash: unset: `MYMAP [baz ': неверный идентификатор
bash: unset: `A] ': неверный идентификатор
$ unset MYMAP ["$ K"] # Вы должны заключать в кавычки переменные, значения которых могут содержать пробелы, когда вы не устанавливаете в ассоциативном массиве
$ echo $ {MYMAP [baz A]}

$ MYMAP [baz A] = quux
$ unset MYMAP ['$ K'] # Любопытно, что одинарные кавычки здесь тоже работают, хотя я бы посоветовал их избегать
$ echo $ {MYMAP [baz A]}

 

Длина

$ declare -A MYMAP = ([foo a] = bar [baz b] = quux)
$ echo $ {# MYMAP [@]} # Количество ключей в ассоциативном массиве
2
$ echo $ # MYMAP [@] # НЕПРАВИЛЬНО
0MYMAP [@]
$ echo $ {# MYMAP} # НЕПРАВИЛЬНО
0
 

Числовая индексация

$ declare -A MYMAP = ([foo a] = bar [baz b] = quux)
$ KEYS = ("$ {! MYMAP [@]}") # Создайте обычный массив, содержащий все ключи в ассоциативном массиве
$ echo $ {KEYS [0]} # Находим ключ по индексу
foo a
$ echo $ {MYMAP [$ {KEYS [0]}]} # Найдите значение по индексу
бар

$ # Цикл с использованием индекса
$ для ((I = 0; $ I
 

Область применения

$ unset MYMAP
$ function createmap () {MYMAP [foo] = bar; } # Неявное создание помещает его в глобальную область видимости
$ echo $ {МОЯ КАРТА [foo]}

$ createmap
$ echo $ {МОЯ КАРТА [foo]}
бар
 
$ unset MYMAP
$ function createmaplocal () {объявить -A MYMAP; MYMAP [foo] = bar; } # Явное создание помещает его в локальную область видимости
$ echo $ {МОЯ КАРТА [foo]}

$ createmaplocal
$ echo $ {МОЯ КАРТА [foo]}

 

Проверка версии Bash

 $ bash --version # Для ассоциативных массивов должна быть как минимум версия 4
GNU bash, версия 4.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *