Переменные интепретатора bash

Январь 21st, 2011 Рубрики: bash, Linux, основы Linux

работа с переменными bashПривет, читателям моего блога. Недавно узнал многое о переменных в интерпретаторе 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!




Теги: , , ,

11 комментариев к “Переменные интепретатора bash”

  1. Дмитрий
    Май 11th, 2012 at 15:51
    1

    Крутой блог, реально спасибо!!! ток вот тут лучше сделать так

    server:~# var10=alex
    server:~# echo $var10’ander’

    У меня не пашит почему-то так как на Вашем примере

    • Май 11th, 2012 at 15:57
      2

      Спасибо.
      и не должно пахать. потому что пример показывает, что будет выведена переменная $var10ander, которой несуществует, а вот echo ${var10}ander выведет значение переменной var10 и дополнит строкой ander.

  2. maksim
    Июнь 19th, 2012 at 16:25
    3

    Спасибо. Разжевано и уложено по нужным местам. У вас два образования? Преподаете?

    • Июнь 19th, 2012 at 20:37
      4

      У вас два образования?

      Высшее — одно.

      Преподаете?

      Преподавать — не преподаю )

  3. FreeOwl
    Сентябрь 16th, 2014 at 16:35
    5

    #!/bin/bash

    echo ScriptName is \>\>$0\<\< |wall
    почему такой код, из крона (at -f script.sh now +1 MINUTE), вместо имени выведет sh

  4. Роман
    Декабрь 4th, 2014 at 23:09
    8

    Здравствуйте! такой вопрос: при написании скрипта возможно ли указать, чтобы переменной присваивалось то, что введет пользователь после появления определенного сообщения?аналог из командного файла Windows:
    {set /p peremennaya= «vvedite znachenie peremennoy:»
    echo %peremennaya%
    }
    результат:
    {vvedite znachenie peremennoy:

    }

    • Декабрь 18th, 2014 at 15:29
      9

      Да, для этого используется read.
      Пример:
      #!/bin/bash
      printf 'Какой Linux дистрибутив Вы знаете? '
      read DISTR

      case $DISTR in
      ubuntu)
      echo "Я тоже знаю Ubuntu! Эта система основана на Debian."
      ;;
      centos|rhel)
      echo "Эй! Это мой любимый серверный дистрибутив!"
      ;;
      windows)
      echo "Очень смешно..."
      ;;
      *)
      echo "Хмм, кажется я никогда не использовал этот дистрибутив."
      ;;
      esac

  5. FreeOwl
    Декабрь 17th, 2014 at 21:56
    10

    всё правильно. Сорри.
    AT запускает команды из файла, а не скрипт :)

    • Декабрь 18th, 2014 at 15:33
      11

      Отлично.
      Рад, что вопрос решен.

Написать комментарий