Os3

Променливи


страницата се нуждае от преглеждане


Променливи в shell

В shell променливите имат име, значение и понякога атрибути.
Името е идентификатор на променливата. То е символен низ, който може да се състои от букви, цифри и символа за подчертаване ("_"). Името на променлива трябва да започва с буква или символа "_" и е case-sensitive (различават се главните от малките букви).
Значението на една променлива е символен низ.
Декларирането на променлива не е задължително. То може да става при присвояване на значение. По default, променливата има значение "" (празен низ), което по-късно може да бъде зададено с командата declare.
Променливата е част от обкръжението на процеса shell (environment), докато процесът завърши или преди да се подаде командата unset, която изключва променливата от обкръжението на процеса.

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

То става по два начина:

С оператор за присвояване, който има следния вид:

име_на_променлива=[значение]
Пример:
x=123
y=
На променливата с име x ще се присвои значението "123", а на променливата с име y ще се присвои празен низ за значение - "".
Значението е низ, който може да е ограден с единични или двойни кавички, но те може и да не присъстват. Ако в низа няма интервали или метасимволи, тогава значението може да е без кавички. Ако присъстват интервали, то е необходимо значението да бъде заградено в кавички, а ако има (и) метасимволи, те се екранират по следното правило:

  • ако низът е заграден в двойни кавички ("низ"), то се екранират всички метасимволи, без $, \, ', ";
  • ако низът е заграден в единични кавички ('низ'), то се екранират всички метасимволи, без '.

С команда read

read име_на_променлива
Командата може да е вътрешна или външна за shell-а. Чете се един ред от стандартния вход и се раделя на думи (разделителен символ е интервал), като всяка дума се съпоставя на съответната променлива (аргумент на променливата). При тази команда може да възникнат несъответствия. Например, при подадени команда read и променливи x, y и z, ето какво ще се случи в следните два случая на четене на низове от стандартния вход:

  • 123 aa bb cc

На x ще се присвои значението "123", на y - значението "аа", а на z - "bb cc".

  • 123 аа

На x ще се присвои значението "123", на y - "aa", a нa z - "" (празен низ).

Други примери за присвояване на значения на променливи:

  • L=Linux, L="Linux" и L='Linux' са един и същ вариант, понеже в значението на променливата няма интервали;
  • D=/home/student/proc/dir1 - тук символът "/" не е метасимвол;
  • OS="Red Hat Linux" и OS='Red Hat Linux' са едно и също, понеже имаме само интервали, но нямаме метасимволи;
  • A="a<b" и A='a<b' са едно и също, т.к. няма нито метасимволи, нито интервали.

Заместване на променлива

Замествания се правят от shell-a, а не от команди.

Конструкциите

$име_на_променлива и ${име_на_променлива}
се заместват със значението на променливата. Втората конструкция се използва, когато {} ограничават името на променливата, например когато след променливата следват символи, които не са отделени от нея с интервали:

  • Пример 1:

L=Linux
OS="Red Hat $L"
Тук се извършва заместване на $L със значението "Linux" на променливата L. В резултат, на променливата с име OS ще се присвои стойността "Red Hat Linux".
OS="Red Hat ${L}7.2"
На променливата с име OS ще се присвои стойността "Red Hat Linux7.2".

  • Пример 2:

D=/home/student/proc/dir1
cd $D
ls -l $D/*.c
Тук $D се замества със значението на променливата D, което в случая е "/home/student/proc/dir1". Пример 2 е еквивалентен на следното:
cd /home/student/proc/dir1
ls -l /home/student/proc/dir1/*.c

Други замествания на променливи:

${име_на_променлива:=дума}
${име_на_променлива:-дума}
${име_на_променлива:+дума}
${име_на_променлива:?дума}
При тези конструкции се проверява дали променливата е определена. Ако променливата е без значение ("", празен низ), то се дава новото значение, което е определено от дума, и се извършва заместването; в противен случай заместване се извършва със старото значение на променливата. Ако липсва ":", то проверката за празен низ не се извършва, а директно се прави заместване на значението на променливата с новото, определено от дума.
трябва да се опише какво правят конструкциите с -, + и ?.//

${име_на_променлива:отместване[:брой]}
С тази конструкция се извършва заместване на подниз, с подадено начало в отместване и дължина, равна на брой. Ако броят на символите, които са дължината на подниза, не е зададен, то се счита, че подниза е до края на значението на променливата.

${#име_на_променлива}
Конструкцията се замества с броя символи в значението на променливата.

Команди за променливи

Те се реализират като вътрешни променливи (обкръжението им е самият shell).

  • echo [опции] [низ …]

Тази команда се използва не само за променливи. Тя извежда на стандартния изход низа (или низовете, ако са няколко) и преминава на нов ред накрая. Командата echo е противоположна на командата read. В по-нови shell-ове, е аналогична на командата printf.

  • set

Командата set се използва най-просто, без аргументи. Тя извежда на стандартния изход всички променливи, които са определени в текущия shell.

  • unset име_на_променлива

Както вече казахме по-горе, тази команда изключва променливата от обкръжението на процеса.

  • export [-n] [променлива …]

export е най-старият атрибут на променливите. Означава, че променливите са част от обкръжението на shell-а. Неекспортни променливи не се предават към поражданите процеси, докато експортните променливи се подават.
Командата, използвана с име на променлива, прави променливата експортна.
-n отменя export.
Само export извежда експортните променливи за shell-a.

  • readonly [променлива …]

С този атрибут (команда), значението на променливата не може да се промени, променливата не може да се unset-не, не може да се махне. Това означава, че readonly действа до края, до завършването на процеса.
Както по-горе, и тук ако се използва само readonly без имена на променливи, то ще се изведат всички променливи, които притежават този атрибут.
Вероятно в новите bash има опция -n към readonly, която отменя атрибута за подадена променлива, но тази опция може и да не работи.

  • declare [опции] [променлива …]

declare се използва за създаване, задаване и настройване на променливи. Някои от опциите на командата са:
-x - атрибут export
-r - атрибут readonly
-i - атрибут integer (което означава, че значенията на променливата докрая са само числа; хубаво е, ако искаме да ползваме аритметика)

Примери:
declare # set (информационна команда)
declare -x # export
declare -r # readonly
declare -xr # export and readonly
A=123; export A
A=123; declare -x A
declare -x A=123
declare +x A # export -n A
# + се използва, за да отменя дадения атрибут

Системни променливи

В login shell (все още нямаме никакви задавания), shell-a прави инициализация на обкръжението. След това, с подаване на set или declare, получаваме няколко екрана с променливи. Някои от тях са доста важни.
Кои са вътрешните системни променливи, зависи и то това, дали имаме shell, csh, bash или др. Ето някои променливи:

  • HOME

Тази променлива означава пълно име на началния каталог на потребителя. Тя може да се променя.
Командата cd е еквивалентна на командата cd $HOME.

  • PATH

Променливата съдържа списък от имена на каталози, в които shell-a търси външни команди.
: се използва за разделител между имената на каталозите.
PATH може да изглежда така:
PATH=/bin:/usr/bin:/usr/local/bin
Примери:
PATH=$PATH:$HOME/bin # това е традиционно; bin може да е с друго име
export PATH # хубаво е да се прави, независимо дали PATH е export или не
# export е добре да се използва за системните променливи

  • PS1

Първична покана (prompt) на shell.
Стандартното означение при обикновен shell e: $ за обикнове потребител и # за администратора.
Означението при bash е: bash$ за обикновен потребител и bash# за администратора.
Но ВЕЧЕ стандартните означения може да са променени в различните шелове.
Ето как може да изглежда променливата PS1:
PS1='\u @ \h \w \$/# '
Тук "\u" означава "user", "\h" - "host", "\w" - "текуща директория (work dir)", "\$/#" - "$" или "#".

  • PS2

Вторична покана на shell. Стандартното означение е >.
Съществуват и PS3 и PS4.

  • UID

User ID - вътрешен идентификатор на потребителя. Има атрибут readonly и intern (ползва се в ядрото).

  • IFS

Internal Field Seperator - това са символите, които се разглеждат като разделители на думи при word splitting и командата read. Стандартно са: "<space><tab><newline>".

  • PWD

Име на текущ каталог.

  • OLDPWD

Име на предишния текущ каталог.

  • USER

Име на потребителя.

  • SHELL

Име на потребителския login shell.

  • BASH

Име на файла с изпълнимия код на bash. Стандартно е /bin/bash, но може да е и /usr/bash или др.

  • BASH_VERSION

Версията на bash.

Инициализиращи командни процедури (profiles)

Тези процедури се изпълняват автоматично при стартиран shell. Обикновено тук се натройват set.
Има няколко инициализиращи командни процедури, изпълняващи се от няколко вида shells:

Profiles за login shell процес.

  • /etc/profile

Това е глобален profile. Изпълнява се първи, ако съществува.

  • ~/.bash_profile или ~/.bash_login или ~/.profile

(Тук ~ е тилда-заместване - т.е. заменя се с началния каталог на потребителя (аналогично на $HOME); . означава, че файлът е скрит.)
Изпълнява се първият намерен и завършва (каквото и да значи това).
Най-често при обикновен shell profile-а, който се използва, е ~/.profile, а при bash - ~/.bash_profile. Те са аналози на AUTOEXEC.BAT.

Profiles за интерактивен не-login shell процес

Такъв процес е например, когато пишем bash в login shell, а profile-а е:

  • ~/.bashrc

който е индивидуален, ако съществува.

Profiles за неинтерактивен shell процес

(Такива се изпълняват при изпълнение на командна процедура)

  • $BASH_LEN

Това е системна променлива и ако има значение, то тя съдържа име на файл.

Заместване на изхода (Command substitution)

`команда` (това е стар синтаксис) или
$(команда) (нов синтаксис)
С тези двата начин се замества командата с това, което тя извежда на стандартния изход.

Примери:
D1=`pwd` или D1=$(pwd)
now=`date` или now=$(date)
num=`who | wc -l` или num=$(who | wc -l)
echo "Number of sessions: `who|wc -l`" #тук заместването е част от аргументите на командата echo

Може в едно заместване да се вложи друго. Тогава е удобно да се използва новия синтаксис.

Аритметични изчисления

Те предоставят небогати средства за обработка на целочислена аритметика.

Команда expr:

Общ вид:
expr израз
Изчислява се значението на подадения целочислен израз и резултатът се извежда на стандартния изход. Важно е да се отбележи, че изразът се конструира от константи (цели числа), променливи (с $) и целочислените аритметични операции: +, -, *, /, %. Скоби (може би все още) няма. Стандартният приоритет се изичслява отляво надясно.
Примери:
x=12
expr $x + 1
expr $x "*" 2 # в случая * е метасимвол, затова е заграден в кавички - за да се приеме като операция
x=`expr $x + 1` # аналогично на x++
expr `who | wc -l` -1

Аритметично разширение (Arithmetic expansion)

$[израз] или $((израз))
Среща се в по-нови версии, не е команда. Първо се изчислява целочисленият израз и след това резултатът замества конструкцията. Изразът се конструира от константи (цели числа), променливи (с или без $), аритметични операции и скоби. Операциите, както и приоритетите им, са както в езика C.
Примери:
x=12
echo $(($x + 1)) # exho $[$x + 1]
echo $(($x * 2)) # в случая * няма нужда от екраниране
x = $[$x + 1] # x=$((x+1)) или : S((x+=1))
# ":" се нарича "празна команда", т.е. не връща/прави нищо

Командна процеруда и аргументи (позиционни параметри)

Обща представа

Командната процедура (команден файл, shell файл, shell script) е текстов файл, съдържащ конструкции на командния език. Изпълнението на една командна процедура завършва с exit [n] или, обикновено, просто като свършат изпълненията на командите в процедурата. Числото n може да го няма, или да е в интервала [0, 255]. Разликата между logout и exit е, че exit може да се използва в командни процедури и след като се изпълни, се връща към родителския процес.
В една командна процедура коментари се правят по следния начин:
# comment
Като се счита, че коментара е до края на реда. Тук # е метасимвол. Изключение за коментар е комбинацията #!, която нямам идея какво означава.
Пример:
# nsession
# - - - - - - - - - - - - - - - - - - - -
date
n=`who | wc -l`
echo "Number of sessions: $n"
# - - - - - - - - - - - - - - - - - - - -
Тази командна процедура изчислява и извежда текущото време и броя на сесиите в системата. Записана е като файл, в текущия каталог, с име nsession.

Изпълнение на командна процедура

Това става с:

  • $ nsession

Но може да бъде изпълнено, ако потребителят има права за изпълнение на файла (тези права може да се придобият с командата chmod a+x nsession) и ако файлът е в каталог от списъка в значението на променливата PATH.
Други начини за извикване на командната процедура:

  • $ bash nsession
  • . nsession

В този случай се изпълнява от текущия shell. Полезно е за изпълнение наново на profile без logout/login. . е синоним на текущия bash процес и няма отношение към правата (executable).

  • /home/student/nsession

Това се използва при неитерактивен bash - задава се пълния път до файла.

  • ./nsession

Ако файлът е в текущия каталог.

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

Имената на позиционните параметри се изписват по следния начин:
$0, $1, $2, …, ${10}, …
където $0 се използва за името на файла с командната процедура, а $i - за i-тия (:P) аргумент на процедурата, зададен след името на файла (при номер на агрумента по-голям от 10, номерът се загражда в {} скоби).
При извикване на командната процедура, значенията на параметрите се присвояват от аргументите в командния ред, или чрез set в процедурата: set 1 2 3 …
Пример:

  1. userlog user_name
  2. - - - - - - - - - - - - - - - - - - - -

n=`who | grep "^$1 " | wc -l`
echo "User $1: $n sessions"

  1. - - - - - - - - - - - - - - - - - - - -

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

Вътрешни променливи

Следва списък с такива (срещу името на съответната променлива е значението й):

  • $# - брой аргументи, подадени на shell-a, без нулевия (аргументът с името на файла с процедурата);
  • $@ - извежда всички аргументи, предадени на shell-a, без нулевия, разделени с интервали; # "$1" "$2" …
  • $* - извежда всичко аргументи, предадени на shell-a, без нулевия, разделени с IFS (input field seperator); не се прави word splitting (word splitting може да прехамва символи, например символа за нов ред); # "$1c$2c…"
  • $? - код на завършване на последната изпълнена команда в привилегирован режим;
  • $$ - идентификатор (pid) на процеса shell;
  • $! - идентификатор (pid) на последния изпълнен фонов процес.

Команда shift

Общият вид на командата е следният:
shift [n]
Измества значенията на аргументите с n значения наляво, т.е. към малките номера. По този начин значенията на първите n аргумента се губят. $0 не участва в изместването, а по премълчаване n = 1. Променят се съответно и значенията на променливите $*, $@ и $#.
Пример:
shift
Тук се прави следното изместване: $2 -> $1, $3 -> $2 и т.н. Старото значение в $1 се губи.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License