Писане на скриптове за BASH шел

Тази статия е преведена с разрешението на автора и X_console.
Адресът на оригиналната статия е .
Както всички шелове, които може да намерите за Linux BASH (Bourne Again SHell) е не само отличен команден интерпретатор, но и език за писане на скриптове. Шел (Shell) скриптовете позволяват максимално да използвате възможностите на шел интерпретатора и да автоматизирате множество задачи. Много от програмите, които може да намерите за Linux в последно време, са шел скриптове. Ако искате да разберете как те работят или как може да ги редактирате е важно да разбирате синтаксиса и семантиката на BASH шела. В допълнение познаването на bash езика позволява да напишете ваши собствени програми, които да изпълняват точно това, което искате.
Програмиране или писане на скриптове?
Хората, които до сега не са се занимавали с програмиране, обикновено не разбират разликата между програмен и скрипт език. Програмните езици обикновено са по-мощни и по-бързи от скрипт езиците. Примери за програмни езици са C, C++, и Java. Програмите, които се пишат на тези езици, обикновено започват от изходен код (source code) – текст, който съдържа инструкции за това как окончателната програма трябва да работи, след което се компилират до изпълним файл. Тези изпълними файлове не могат лесно да бъдат адаптирани за различни операционни системи (ОС). Например, ако сте написали програма на C за Linux, изпълнимият файл няма да тръгне под Windows 98. За да можете да я използвате тази програма се налага да прекомпилирате изходния код под Windows 98. Скриптовете (програмите писани на скрипт езици) също започват от изходен, но не се компилират в изпълними файлове. При тях се използва интерпретатор, който чете инструкциите от изходния код и ги изпълнява. За жалост, поради това че интерпретатора трябва да прочете всяка команда преди да я изпълни, интерпретираните програми вървят като цяло по-бавно спрямо компилираните. Основното предимство на скриптовете е, че лесно могат да бъдат пренаписани за други ОС стига да има интерпретатор за тази ОС. bash е скрипт език. Той е идеален за малки програми. Други скрипт езици са Perl, Lisp, и Tcl.
Какво искате да знаете?
Писането на собствени шел скриптове изисква да знаете най-основните команди на Linux. Трябва да знаете например как да копирате, местите или създавате нови файлове. Едно от нещата, които е задължително да знаете е, как да работите с текстов редактор. За Linux има множество текстови редактори, най-разпространените от които са vi, emacs, pico, mcedit.
Внимание!!!
Не се упражнявайте в писане на скриптове като root потребител! Не се знае какво може да се случи! Имайте това в предвид! За упражненията използвайте нормален потребител без права на root.
Вашият първи BASH скрипт
Първият скрипт, който ще напишете, е класическата "Hello World" програма. Тази програма изпечатва единствено думите "Hello World" на екрана. Отворете любимия си текстов редактор и напишете:
#!/bin/bash
echo "Hello World"
Първият ред от програмата казва,, че ще използваме bash интерпретатора за да подкараме програмата. В този случай bash се намира в /bin директорията. Ако bash се намира в друга директория на вашата система, тогава направете необходимите премени в първия ред. Изричното споменаване на това кой интерпретататор ще изпълнява скрипта е много важно, тъи като той казва на Linux какви инструкции могат да бъдат използвани в скрипта. Следващото нещо, което трябва да направите, е да запишете файла под името hello.sh. Остава само да направите файла изпълним. За целта напишете:
xconsole$ chmod 700 ./hello.sh
Прочетете упътването за използване на chmod командата, ако не знаете как да променяте правата на даден файл. След като сте направили програмата изпълнима, я стартирайте, като напишете:
xconsole$ ./hello.sh
Резултатът ще бъде следният надпис на екрана:
Hello World
Това е! Запомнете последователността от действия - писане на кода, записване на файла с кода, и променянето на файла в изпълним с командата chmod.
Команди, Команди, Команди
Какво точно направи вашата първа програма? Тя изпечата думите "Hello World" на екрана. Но как програмата го направи това? С помощта на команди. Единственият ред с команди беше echo "Hello World". И коя е командата? echo. Командата echo изпечатва всичко на екрана, което е получила като свой аргумент.
Аргумент е всичко, което е написано след името на командата. В нашия случай това е "Hello World". Когато напишете ls /home/root, командата е ls а нейният аргумент е /home/root. Какво означава всичко това? Това означава, че ако имате програма или команда, която изпечатва аргументите си на екрана, то може да я използвате вместо echo. Нека да предположим, че имаме такава команда, която се казва foo. Тази команда ще изпечата своите аргументи на екрана. Тогава нашият скрипт може да изглежда така:
#!/bin/bash
foo "Hello World"
Запишете го и го направете изпълним с chmod след което го стартирайте:
xconsole$ ./hello
Hello World
Точно същият резултат. Всичко, което правихте до сега, е да използвате echo командата във вашия шел скрипт. Друга команда за изпечатване е printf. Командата printf позволява повече контрол при изпечатване на информацията, особено ако сте запознати с програмния език C. Фактически съшият резултат от нашият скрипт можем да постигнем, просто ако напишем в командния ред:
xconsole$ echo "Hello World"
Hello World
Както виждате може да използвате Linux команди при писането на шел скриптове. Вашият bash шел скрипт е колекция от различни програми, специално написани заедно, за да изпълнят конкретна задача.
Малко по-лесни програми
Сега ще напишем програма, с която да преместим всички файлове от дадена директория в нова директория, след което ще изтрием новата директория заедно със нейното съдържание и ще я създадем отново. Това може да бъде направено със следната последователност от команди:
xconsole$ mkdir trash
xconsole$ mv * trash
xconsole$ rm -rf trash
xconsole$ mkdir trash
Вместо да пишем последователно тези команди можем да ги запишем във файл:
#!/bin/bash
mkdir trash
mv * trash
rm -rf trash
mkdir trash
echo "Deleted all files!"
Запишете файла под името clean.sh. След като стартирате clean.sh, той ще премести всички файлове в директория trash, след което ще изтрие директорията заедно със съдържанието и ще я създаде отново. Дори ще изпечата съобщение на екрана, когато свърши с тези действия. Този пример показва и как да автоматизирате многократното писане на последователности от команди.
Коментари във скрипта
Коментарите помагат да направите вашата програма по-лесна за разбиране. Те не променят нищо в изпълнението на самата програма . Те се използват единствено, за да може вие да ги четете. Всички коментари в bash започват със символа: "#", с изключение на първия ред (#!/bin/bash). Първият ред не е команда. Всички редове след първия, които започват със "#", са коментари. Вижте кода на следния скрипт:
#!/bin/bash
# tazi programa broi chislata ot 1 do 10:
for i in 1 2 3 4 5 6 7 8 9 10; do
echo $i
done
Дори и да не знаете bash, веднага може да се ориентирате какво прави скрипта, след като прочетете коментара. Добре е при писане на скриптове да използвате коментари. Ще откриете, че ако ви се наложи да промените някоя програма, която сте писали преди време, коментарите ще ви бъдат от голяма полза.
Променливи
Променливите най-общо казано са "кутии" които съхраняват информация. Вие може да използвате променливи за много неща. Те ви помагат да съхранявате информацията, която е въвел потребителя, аргументи или числова информация. Погледнете този код:
#!/bin/bash
x=12
echo "Stoinosta na promenliwata x e $x"
Всичко, което се случва е да присвоим на променливата x стойност 12 и да отпечатаме тази стойност с комадата echo. echo "Stoinosta na promenliwata x e $x" изпечатва текущата стойност на x. Когато давате стойност на дадена променлива, не трябва да има шпации между нея и "=". Ето какъв е синтаксиса:
име_на_променлива=стойност
Стойността на променливата можем да получим като поставим символа "$" пред нея. В конкретния случай за да изпечатаме стойността на& x пишем echo $x.
Има два типа променливи - локални променливи и променливи на обкръжението (environment). Променливите на обкръжението се задават от системата и информация за тях може да се получи като се използва env командата. Например:
xconsole$ echo $SHELL
Ще отпечата
/bin/bash
Което е името на шела, който използваме в момента. Променливите на обкръжението са дефинирани в /etc/profile и ~/.bash_profile. С echo командата можете лесно да проверите текущата стойност на дадена променлива, била тя от обкръжението или локална. Ако все още се чудите защо са ни нужни променливи, следната програма е добър пример, който илюстрира тяхното използване:
#!/bin/bash
echo "Stojnosta na x e 12."
echo "Az imam 12 moliwa."
echo "Toj mi kaza che stojnosta na x e 12."
echo "Az sym na 12 godini."
echo "Kak taka stojnosta na x e 12?"
Да предположим, че в един момент решите да промените стойността на x от 12 на 8. Какво трябва да направите? Трябва да промените навсякъде в кода 12 с 8. Да но... има редове, в които 12 не е стойността на x. Трябва ли да променяме и тези редове? Не, защото те не са свързани с x. Не е ли объркващо? По-надолу е същият пример, само че се използват променливи:
#!/bin/bash
x=12 # stoinosta na promenliwata x e 12 e x
echo "Stoinosta na x e $x."
echo "Az imam 12 moliwa."
echo "Toj mi kaza che stojnosta na x e $x."
echo "Az sym na 12 godini."
echo "Kak taka stojnosta na x e $x?"
В този пример $x ще изпечата текущата стойност на x, която е 12. По този начин ако искате да промените стойността на x от 12 на 8 е необходимо единствено да замените реда в който пише x=12 с x=8. Другите редовете няма да бъдат променени. Променливите имат и други полезни свойства, както ще се убедите сами в последствие.
Писане на скриптове за BASH шел : версия 1.2 (част 2)
Тази статия е преведена с разрешението на автора и X_console.
Адресът на оригиналната статия е .
Продължениe на [ част 1 ].
Условни оператори
Условните оператори позволяват вашата програма да "взема решения" и я правят по-компактна. Което е по-важно – с тях може да проверявате за грешки. Всички примери до сега започваха изпълнението си от първия ред до последния без никакви проверки. За пример:
#!/bin/bash
cp /etc/foo .
echo "Done."
Тази малка шел програма копира файла /etc/foo в текущата директория и изпечатва "Done" на екрана. Тази програма ще работи само при едно условие. Трябва да има файл /etc/foo. В противен случай ще се получи следният резултат:
xconsole$ ./bar.sh
cp: /etc/foo: No such file or directory
Done.
Както виждате, имаме проблем. Не всеки, който стартира вашата програма, има файл /etc/foo на системата си. Ще бъде по-добре, ако вашата програма проверява дали файла /etc/foo съществува и ако това е така, да продължи с копирането, в противен случай да спре изпълнението. С "псевдо" код това изглежда така:
if /etc/code exists, then
copy /etc/code to the current directory
print "Done." to the screen.
otherwise,
print "This file does not exist." to the screen
exit
Може ли това да бъде направено с bash? Разбира се! В bash условните оператори са: if, while, until, for, и case. Всеки оператор започва с ключова дума и завършва с ключова дума. Например if оператора започва с ключовата дума if, и завършва с fi. Условните оператори не са програми във вашата система. Те са вградени свойства на bash.
if ... else ... elif ... fi
Е един от най-често използваните условни оператори. Той дава възможност на програма да вземе решения от рода на "направи това ако(if) това условие е изпълнено, или(else) прави нещо друго". За да използвате ефективно условния оператор if, трябва да използвате командата test. test проверява за съществуване на файл, права, подобия или разлики. Ето програмата bar.sh:
#!/bin/bash
if test -f /etc/foo
then
# file exists, so copy and print a message.
cp /etc/foo .
echo "Done."
else
# file does NOT exist, so we print a message and exit.
echo "This file does not exist."
exit
fi
Забележете че редовете след then и else са малко по-навътре. Това не е задължително, но се прави с цел програмата да бъде по-лесна за четене. Сега стартирайте програмата. Ако имате файл /etc/foo, тогава програмата ще го копира в текущата директория, в противен случай ще върне съобщение за грешка. Опцията -f проверява дали това е обикновен файл. Ето списък с опциите на командата test:
-d проверява дали файлът е директория
-e проверява дали файлът съществува
-f проверява дали файлът е обикновен файл
-g проверява дали файлът има SGID права
-r проверява дали файлът може да се чете
-s проверява дали размерът на файла не е 0
-u проверява дали файлът има SUID права
-w проверява дали върху файлът може да се пише
-x проверява дали файлът е изпълним
else се използва, ако искате вашата програма да направи нещо друго, ако първото условие не е изпълнено. Има и ключова дума elif, която може да бъде използвана вместо да пишете друг if вътре в първия if. elif идва от английското "else if". Използва се, когато първото условие не е изпълнено и искате да проверите за друго условие.
Ако не се чувствате комфортно с if и test синтаксиса, който е :
if test -f /etc/foo
then
тогава може да използвате следния вариант:
if [ -f /etc/foo ]; then
Квадратните скоби формират test командата. Ако имате опит в програмирането на C този синтакс може да ви се стори по-удобен. Забележете, че трябва да има разстояние след отварящата квадратна скоба и преди затварящата. Точката и запетаята: ";" казва на шела че това е края на командата. Всичко след ";" ще бъде изпълнено сякаш се намира на следващия ред. Това прави програмата малко по-четима. Можете разбира се да сложите then на следващия ред.
Когато използваме променливи с test е добре да ги заградим с кавички. Например:
if [ "$name" -eq 5 ]; then
while ... do ... done
while оператора е условен оператор за цикъл. Най-общо казано, това което прави е "while(докато) това условие е вярно, do(изпълни) командите done ". Нека да видим следния пример:
#!/bin/bash
while true; do
echo "Press CTRL-C to quit."
done
true в действителност е програма. Това което прави тази програма е да се изпълнява безкрайно. Използването на true се смята, че забавя вашата програма, защото шел интерпретатора първо трябва да извика програмата и след това да я изпълни. Вместо това може да използвате командата ":":
#!/bin/bash
while :; do
echo "Press CTRL-C to quit."
done
По този начин вие постигате същия резултат, но доста по бързо. Единствения недостатък е, че програмата става по-трудно четима. Ето един по-подробен пример, който използва променливи:
#!/bin/bash
x=0; # initialize x to 0
while [ "$x" -le 10 ]; do
echo "Current value of x: $x"
# increment the value of x:
x=$(expr $x + 1)
sleep 1
done
Както виждате използваме test (записана като квадратни скоби) за да проверим състоянието на променливата x. Опцията -le проверява дали x е по-малко (less) или равно (equal) на 10. На говорим език това се превежда по следния начин "Докато (while) x е по-малко или равно на 10, покажи текущата стойност на x, и след това добави 1 към текущата стойност на x.". sleep 1 казва на програмата да спре изпълнението си за една секунда. Както виждате това което правим тук в да проверим за равенство. Ето списък с някой опции на test:
Проверка за равенства между променливите x и y, ако променливите са числа:
x -eq y Проверява дали x е равно на y
x -ne y Проверява дали x не е равно на y
x -gt y Проверява дали x е по-голямо от y
x -lt y Проверява дали x е по-малко от y
Проверка за равенства между променливите x и y, ако променливите са текст:
x = y Проверява дали x е същата като y
x != y Проверява дали x не е същата като y
-n x Проверява дали x не е празен текст
-z x Проверява дали x е празен текст
От горния пример единственият ред, който може да ви се стори по-труден за разбиране е следния:
x=$(expr $x + 1)
Това което прави този ред е да увеличи стойността на x с 1. Но какво значи $(...)? Дали е променлива? Не. На практика това е начин да кажете на шел интерпретатора, че ще изпълнявате командата expr $x + 1, и резултатът от тази команда ще бъде присвоен на x. Всяка команда, която бъде записана в $(...), ще бъде изпълнена:
#!/bin/bash
me=$(whoami)
echo "I am $me."
Опитайте с този пример, за да разберете какво имам предвид. Горната програмка може да бъде написана по-следния начин:
#!/bin/bash
echo "I am $(whoami)."
Сами си решете кой от начините е по-лесен за вас. Има и друг начин да изпълните команда или да присвоите резултата от изпълнението на дадена команда на променлива. Този начин ще бъде обяснен по-нататък. За сега използвайте $(...).
until ... do ... done
Условният оператор until е много близък до while. Единствената разлика е, че се обръща смисъла на условието и се взима предвид новото значение. Действието на until оператора е "докато (until) това условие е вярно, изпълнявай (do) командите". Ето пример:
#!/bin/bash
x=0
until [ "$x" -ge 10 ]; do
echo "Current value of x: $x"
x=$(expr $x + 1)
sleep 1
done
Този код може би ви изглежда познат. Проверете го и вижте какво прави. until ще изпълнява командите докато стойността на променливата x е по-голяма или равна на 10. Когато стойността на x стане 10, цикълът ще спре. Ето защо последната стойност на x, която ще се изпечата е 9.
for ... in ... do ... done
for се използва когато искате да присвоите на дадена променлива набор от стойности. Например можете да напишете програма, която да изпечатва 10 точки всяка секунда:
#!/bin/bash
echo -n "Checking system for errors"
for dots in 1 2 3 4 5 6 7 8 9 10; do
echo -n "."
done
echo "System clean."
В случай, че не знаете опцията -n на командата echo спира автоматичното добавяне на нов ред. Пробвайте командата веднъж с -n опцията и веднъж без нея за да разберете за какво става дума. Променливата dots преминава през стойностите от 1 до 10. Вижте следния пример:
#!/bin/bash
for x in paper pencil pen; do
echo "The value of variable x is: $x"
sleep 1
done
Когато стартирате програмата ще видите че x в началото ще има стойност paper, след което ще премине на следващата стойност, която е pencil, и след това pen. Когато свършат стойностите през който минава цикъла изпълнението му завършва.
Ето една доста полезна програма. Тя добавя .html разширение на всички файлове в текущата директория:
#!/bin/bash
for file in *; do
echo "Adding .html extension to $file..."
mv $file $file.html
sleep 1
done
Ако не знаете "*" е "wild card character". Това ще рече "всичко в текущата директория", което в нашия случай представлява всички файлове в тази директория. Променливата file ще премине през всички стойности, в този случай файловете в текущата директория. След което командата mv преименува стойностите на променливата file във такива с .html разширение.
case ... in ... esac
Условния оператор case е близък до if . За предпочитане е да се използва, когато имаме голям брой условия, които трябва да бъдат проверени. Вземете за пример следния код:
#!/bin/bash
x=5 # initialize x to 5
# now check the value of x:
case $x in
0) echo "Value of x is 0."
;;
5) echo "Value of x is 5."
;;
9) echo "Value of x is 9."
;;*) echo "Unrecognized value."
esac
Операторът case ще провери стойност на x на коя от 3-те възможности отговаря. В този случай първо ще провери дали стойностра на x е 0, след което ще провери за 5 и 9. Накрая ако никое от условия не е изпълнено ще се изпечата съобщението "Unrecognized value.". Имайте предвид, че "*" означава "всичко", и в този случай това означава "която и да е стойност различна от посочените". Ако стойността на x е различна от 0, 5, или 9, то тогава тя попада в случая "*". Когато използвате case, всяко условие трябва да завършва с две ";". Може би се чудите защо да използвате case, когато може да използвате if? Ето как изглежда еквивалентната програма, написана с if. Вижте коя програма е по-бърза и по лесна за четене:
#!/bin/bash
x=5 # initialize x to 5
if [ "$x" -eq 0 ]; then
echo "Value of x is 0."
elif [ "$x" -eq 5 ]; then
echo "Value of x is 5."
elif [ "$x" -eq 9 ]; then
echo "Value of x is 9."
else
echo "Unrecognized value."
fi
Писане на скриптове за BASH шел : версия 1.2 (част 3)
Тази статия е преведена с разрешението на автора и X_console.
Адресът на оригиналната статия е .
Продължениe на [ част 2 ].
Кавички
Кавичките играят голяма роля в шел програмирането. Има три различни вида: двойни кавички: ", единична кавичка: ', и обратно наклонена кавичка: `. Различават ли се те една от друга? - Да.
Обикновено използваме двойната кавичка, за да обозначим с нея низ от символи и да запазим шпацията. Например "Този низ съдържа шпации.". Низ заграден от двойни кавички се третира като един аргумент. Вземете следният скрипт за пример:
xconsole$ mkdir hello world
xconsole$ ls -F
hello/ world/
Създадохме две директории. Командата mkdir взе думите hello и world като два аргумента, създавайки по този начин две директории. А какво ще се случи сега:
xconsole$ mkdir "hello world"
xconsole$ ls -F
hello/ hello world/ world/
Създадохме една директория, състояща се от две думи. Двойните кавички направиха командата да третира двете думи като един аргумент . Без тях mkdir щеше да приеме hello за първи аргумент и world за втори.
Единична кавичка се използва обикновено, когато се занимаваме с променливи. Ако една променлива е заградена от двойни кавички, то нейната стойност ще бъде оценена. Но това няма да се случи ако използваме единични кавички. За да ви стане по-ясно, разгледайте следния пример:
#!/bin/bash
x=5 # stojnosta na x e 5
# izpolzwame dwojni kawichki
echo "Using double quotes, the value of x is: $x"
# izpolzwame edinichni kawichki
echo 'Using forward quotes, the value of x is: $x'
Виждате ли разликата? Може да използвате двойни кавички, ако не смятате да слагате и променливи в низа, който ще заграждат кавичките. Ако се чудите дали единичните кавички запазват шпациите в даден низ, както това правят двойните кавички, погледнете следния пример:
xconsole$ mkdir 'hello world'
xconsole$ ls -F
hello world/
Обратно наклонените кавички коренно се различават от двойните и единични кавички. Те не се използват, за да запазват шпациите. Ако си спомняте, по-рано използвахме следния ред:
x=$(expr $x + 1)
Както вече знаете резултатът от командата expr $x + 1 се присвоява на променливата x. Същият този резултат може да бъде постигнат, ако използваме обратно наклонени кавички:
x=`expr $x + 1`
Кой от начините да използвате? Този, който предпочитате. Ще откриете, че обратно наклонените кавички са по-често използвани от $(...). В много случай обаче $(...) прави кода по-лесен за четене. Вземете предвид това:
$!/bin/bash
echo "I am `whoami`"
Аритметически операции с BASH
bash ви позволява да смятате различни аритметични изрази. Както вече видяхте, аритметическите операции се използват посредством командата expr. Тази команда обаче, както и командата true, се смятат за доста бавни. Причината за това е, че шел интерпретаторът трябва всеки път да стартира true и expr командите, за да ги използва. Като алтернатива на true посочихме командата ":". А като алтернатива на expr ще изпозваме следния израз $((...)). Разликата със $(...) е броя на скобите. Нека да опитаме:
#!/bin/bash
x=8 # stojnosta na x e 8
y=4 # stojnosta na y e 4
# sega shte priswojm sumata na promenliwite x i y na promenliwata z:
z=$(($x + $y))
echo "Sum na $x + $y e $z"
Ако се чувствате по-комфортно с expr вместо $((...)), тогава го използвайте него.
С bash можете да събирате, изваждате, умножавате, делите числа, както и да делите по модул. Ето и техните символи:
ДЕЙСТВИЕ ОПЕРАТОР
Събиране +
Изваждане -
Умножение *
Деление /
Деление по модул %
Всеки от Вас би трябвало да знае какво правят първите четири оператора. Ако не знаете какво означава деление по модул - това е остатъкът при деление на две стойности. Ето и малко bash аритметика:
#!/bin/bash
x=5 # initialize x to 5
y=3 # initialize y to 3
add=$(($x + $y)) # sumiraj x sys y i priswoj rezultata na promenliwata add
sub=$(($x - $y)) # izwadi ot x y i priswoj rezultata na promenliwata sub
mul=$(($x * $y)) # umnozhi x po y i priswoj rezultata na promenliwata mul
div=$(($x / $y)) # razdeli x na y i priswoj rezultata na promenliwata div
mod=$(($x % $y)) # priswoj ostatyka pri delenie na x / y na promenliwata mod
# otpechataj otgoworite:
echo "Suma: $add"
echo "Razlika: $sub"
echo "Projzwedenie: $mul"
echo "Quotient: $div"
echo "Ostatyk: $mod"
Отново горният код можеше да бъде написан с командата expr. Например вместо add=$(($x + $y)), щяхме да пишем add=$(expr $x + $y), или add=`expr $x + $y`.
Четене на информация от клавиатурата
Сега вече идваме към интересната част. Вие можете да направите Вашите програми да си взаимодействат с потребителя и потребителят да може да си взаимодейства с програмата. Командата, която Ви позволява да прочетете каква стойност в въвел потребителят е read. read е вградена в bash команда, която се използва съвместно с променливи, както ще видите:
#!/bin/bash
# gets the name of the user and prints a greeting
echo -n "Enter your name: "
read user_name
echo "Hello $user_name!"
Променливата тук е user_name. Разбира се, може да я наречете, както си искате. read ще Ви изчака да въведете нещо и да натиснете клавиша ENTER. Ако не натиснете нищо, командата read ще чака, докато натиснете ENTER. Ако ENTER е натиснат, без да е въведено нещо, то ще продължи изпълнението на програмата от следващия ред. Ето и пример:
#!/bin/bash
# gets the name of the user and prints a greeting
echo -n "Enter your name: "
read user_name
# the user did not enter anything:
if [ -z "$user_name" ]; then
echo "You did not tell me your name!"
exit
fi
echo "Hello $user_name!"
Ако потребителят натисне само клавиша ENTER, нашата програма ще се оплаче и ще прекрати изпълнението си. В противен случай ще изпечата поздравление. Четенето на информацията, която се въвежда от клавиатурата е полезно, когато правите интерактивни програми, които изискват потребителят да отговори на конкретни въпроси.
Функции
Функциите правят скрипта по-лесен за поддържане. Най-общо казано, функциите разделят програмата на малки части. Функциите изпълняват действия, които Вие сте дефинирали и може да върне стойност от изпълнението си ако желаете. Преди да продължим, ще Ви покажа един пример на шел програма, която използва функция:
#!/bin/bash
# functiqta hello() samo izpechatwa syobshtenie
hello()
{
echo "Wie ste wyw funkciq hello()"
}
echo "Izwikwame funkciqta hello()..."
# izwikwame hello() funkciqta wytre w shell skripta:
hello
echo "Weche izleznahte ot funkciqta hello()"
Опитайте се да напишете тази програма и да я стартирате. Единствената цел на функцията hello() е да изпечата съобщение. Функциите естествено могат да изпълняват и по-сложни задачи. В горния пример ние извикахме функцията hello() с този ред:
hello
Когато се изпълнява този ред, bash интерпретаторът претърсва скрипта за ред, който започва с hello(). След което открива този ред и изпълнява съдържанието на функцията.
Функциите винаги се извикват чрез тяхното име. Когато пишете функция, можете да започнете функцията с function_name(), както беше направено в горния пример, или да използвате думата function т.е function function_name(). Другият начин, по който можем да започнем нашата функция е function hello():
function hello()
{
echo "Wie ste wyw funkciq hello()"
}
Функциите винаги започват с отваряща и затваряща скоба"()", последвани от отварящи и затварящи къдрави скоби: "{...}". Тези къдрави скоби бележат началото и края на функцията. Всеки ред с код, затворен в тези скоби ще бъде изпълнен и ще принадлежи единствено на функцията. Функциите трябва винаги да бъдат дефинирани преди да бъдат извикани. Нека погледнем нашата програма, само че този път ще извикаме функцията преди да е дефинирана:
#!/bin/bash
echo "Izwikwame funkciqta hello()..."
# call the hello() function:
hello
echo "Weche izleznahte ot funkciqta hello()"
# function hello() just prints a message
hello()
{
echo "Wie ste wyw funkciq hello()"
}
Ето какъв е резултатът, когато се опитаме да изпълним програмата:
xconsole$ ./hello.sh
Izwikwame funkciqta hello()...
./hello.sh: hello: command not found
Weche izleznahte ot funkciqta hello()
Както виждате, програмата върна грешка. Ето защо е добре да пишете вашите функции в началото на скрипта или поне преди да ги извикате. Ето друг пример как да използваме функции:
#!/bin/bash
# admin.sh - administrative tool
# function new_user() creates a new user account
new_user()
{
echo "Preparing to add a new user..."
sleep 2
adduser # run the adduser program
}
echo "1. Add user"
echo "2. Exit"
echo "Enter your choice: "
read choice
case $choice in
1) new_user # call the new_user() function
;;*) exit
;;
esac
За да работи правилно тази програма трябва да сте влезли като root, тъй като adduser е програма, която само root потребителят има право да изпълнява. Да се надяваме, че този кратък пример Ви е убедил в полезноста на фукциите.
Прихващане не сигнали
Може да използвате вградената команда trap< за да прихващате сигнали във вашата програма. Това е добър начин да излезете нормално от програмата. Например, ако имате вървяща програма при натискането на CTRL-C ще изпратите на програмата interrupt сигнал, който ще "убие" програмата. trap; ще ви позволи да прихване този сигнал и ще ви даде възможност или да продължите с изпълнението на програмата, или да съобщите на потребителя, че програмата спира изпълнението си. trap има следния синтаксис:
trap dejstwie signal
dejstwie указва какво да искате да направите, когато прихванете даден сигнал, а signal е сигналът, който очакваме. Списък със сигналите може да откриете като пишете trap -l. Когато използвате сигнали във Вашата шел програма пропуснете първите три букви на сигнала, обикновено те са SIG. Например, ако сигналът за прекъсване е SIGINT, във Вашата шел програма използвайте само INT. Можете да използвате и номера на сигнала. Номерът на сигнала SIGINT е 2. Пробвайте следната програма:
#!/bin/bash
# using the trap command
# da se zipylni funkciqta sorry() pri natiskane na CTRL-C:
trap sorry INT
# function sorry() prints a message
sorry()
{
echo "I'm sorry Dave. I can't do that."
sleep 3
}
# count down from 10 to 1:
for i in 10 9 8 7 6 5 4 3 2 1; do
echo $i seconds until system failure."
sleep 1
done
echo "System failure."
Сега, докато програмата върви и брои числа в обратен ред, натиснете CTRL-C. Това ще изпрати сигнал за прекъсване на програмата. Сигналът ще бъде прихванат от trap командата, която ще изпълни sorry() функцията. Можете да накарате trap да игнорира сигнал като поставите "'&#32;'" на мястото на действие. Можете да накарате trap да не прихваща сигнал като използвате "-". Например:
# izpylni sorry() funkciqta kogato programa poluchi signal SIGINT:
trap sorry INT
# nakaraj programata da NE prihwashta SIGINT signala :
trap - INT
# ne prawi nishto kogato se prihwane signal SIGINT:
trap '&#32;' INT
Когато кажете на trap да не прихваща сигнала, то програмата се подчинява на основното действие на сигнал, което в конкретния случай е да прекъсне програмата и да я "убие". Когато укажете trap да не прави нищо при получаване на конкретен сигнал, то програмата ще продължи своето действие, игнорирайки сигнала.
Вижте [ Част 1| Част 2 | Част 3 | Част 4 ]
Тази статия е преведена с разрешението на автора и X_console.
Адресът на оригиналната статия е .
Продължениe на [ част 2 ].
Кавички
Кавичките играят голяма роля в шел програмирането. Има три различни вида: двойни кавички: ", единична кавичка: ', и обратно наклонена кавичка: `. Различават ли се те една от друга? Да.
Обикновено използваме двойната кавичка, за да обозначим с нея низ от символи и да запазим шпацията. Например "Този низ съдържа шпации.". Низ заграден от двойни кавички се третира като един аргумент. Вземете следния скрипт за пример:
xconsole$ mkdir hello world
xconsole$ ls -F
hello/ world/
Създадохме две директории. Командата mkdir взе думите hello и world като два аргумента, създавайки по този начин две директории. А какво ще се случи сега:
xconsole$ mkdir "hello world"
xconsole$ ls -F
hello/ hello world/ world/
Създадохме една директория, състояща се от две думи. Двойните кавички направиха командата да третира двете думи като един аргумент . Без тях mkdir щеше да приеме hello за първи аргумент и world за втори.
Единична кавичка се използва обикновено, когато се занимаваме с променливи. Ако една променлива е заградена от двойни кавички, то нейната стойност ще бъде оценена. Но това няма да се случи ако използваме единични кавички. За да Ви стане по-ясно разгледайте следния пример:
#!/bin/bash
x=5 # stojnosta na x e 5
# izpolzwame dwojni kawichki
echo "Using double quotes, the value of x is: $x"
# izpolzwame edinichni kawichki
echo 'Using forward quotes, the value of x is: $x'
Виждате ли разликата? Може да използвате двойни кавички, ако не смятате да слагате и променливи в низа, който ще заграждат кавичките. Ако се чудите дали единичните кавички запазват шпациите в даден низ, както това правят двойните кавички, погледнете следния пример:
xconsole$ mkdir 'hello world'
xconsole$ ls -F
hello world/
Обратно наклонените кавички коренно се различават от двойните и единични кавички. Те не се използват, за да запазват шпациите. Ако си спомняте по-рано използвахме следния ред:
x=$(expr $x + 1)
Както вече знаете, резултатът от командата expr $x + 1 се присвоява на променливата x. Същият този резултат може да бъде постигнат ако използваме обратно наклонени кавички:
x=`expr $x + 1`
Кой от начините да използвате? Този, който предпочитате. Ще откриете, че обратно наклонените кавички са по-често използвани от $(...). В много случаи обаче $(...) прави кода по-лесен за четене. Вземете предвид това:
$!/bin/bash
echo "I am `whoami`"
Аритметически операции с BASH
bash ви позволява да смятате различни аритметични изрази. Както вече видяхте аритметическите операции се използват посредством командата expr. Тaзи команда, обаче, както и командата true се смята, че са доста бавни. Причината за това е, че шел интерпретаторът трябва всеки път да стартира true и expr командите, за да ги използва. Като алтернатива на true посочихме командата ":". А като алтернатива на expr ще изпозваме следния израз $((...)). Разликата със $(...) е броят на скобите. Нека да опитаме:
#!/bin/bash
x=8 # stojnosta na x e 8
y=4 # stojnosta na y e 4
# sega shte priswojm sumata na promenliwite x i y na promenliwata z:
z=$(($x + $y))
echo "Sum na $x + $y e $z"
Ако се чувствате по-комфортно с expr вместо $((...)), тогава използвайте него.
С bash можете да събирате, изваждате, умножавате, делите числа, както и да делите по модул. Ето и техните символи:
ДЕЙСТВИЕ ОПЕРАТОР
Събиране +
Изваждане -
Умножение *
Деление /
Деление по модул %
Всеки от Вас би трябвало да знае какво правят първите четири оператора. Ако не знаете какво означава деление по модул това е остатъкът при деление на две стойности. Ето и малко bash аритметика:
#!/bin/bash
x=5 # initialize x to 5
y=3 # initialize y to 3
add=$(($x + $y)) # sumiraj x sys y i priswoj rezultata na promenliwata add
sub=$(($x - $y)) # izwadi ot x y i priswoj rezultata na promenliwata sub
mul=$(($x * $y)) # umnozhi x po y i priswoj rezultata na promenliwata mul
div=$(($x / $y)) # razdeli x na y i priswoj rezultata na promenliwata div
mod=$(($x % $y)) # priswoj ostatyka pri delenie na x / y na promenliwata mod
# otpechataj otgoworite:
echo "Suma: $add"
echo "Razlika: $sub"
echo "Projzwedenie: $mul"
echo "Quotient: $div"
echo "Ostatyk: $mod"
Отново горният код можеше да бъде нашисан с командата expr. Например вместо add=$(($x + $y)), щяхме да пишем add=$(expr $x + $y), или add=`expr $x + $y`.
Четене на информация от клавиатурата
Сега вече идваме към интересната част. Вие можете да направите Вашите програми да си взаимодействат с потребителя и потребителят да може да си взаимодейства с програмата. Командата която Ви позволява да прочетете каква стойност в въвел потребителят е read. read е вградена в bash команда, която се използва съвместно с променливи, както ще видите:
#!/bin/bash
# gets the name of the user and prints a greeting
echo -n "Enter your name: "
read user_name
echo "Hello $user_name!"
Променливата тук е user_name. Разбира се, може да я наречете, както си искате. read ще ви изчака да въведето нещо и да натиснете клавиша ENTER. Ако не натиснете нищо, командата read ще чака, докато натиснете ENTER . Ако ENTER е натиснат, без да е въведено нещо, то ще продължи изпълнението на програмата от следващия ред. Ето и пример:
#!/bin/bash
# gets the name of the user and prints a greeting
echo -n "Enter your name: "
read user_name
# the user did not enter anything:
if [ -z "$user_name" ]; then
echo "You did not tell me your name!"
exit
fi
echo "Hello $user_name!"
Ако потребителят натисне само клавиша ENTER, нашата програма ще се оплаче и ще прекрати изпълнението си. В противен случай ще изпечата поздравление. Четенето на информацията, която се въвежда от клавиатурата е полезно, когато правите интерактивни програми, които изискват потребителят да отговори на конкретни въпроси.
Функции
Функциите правят скрипта по-лесен за поддържане. Най-общо казано, функциите разделят програмата на малки части. Функциите изпълняват действия, които Вие сте дефинирали и може да върне стойност от изпълнението си ако желаете. Преди да продължим, ще Ви покажа един пример на шел програма, която използва функция:
#!/bin/bash
# functiqta hello() samo izpechatwa syobshtenie
hello()
{
echo "Wie ste wyw funkciq hello()"
}
echo "Izwikwame funkciqta hello()..."
# izwikwame hello() funkciqta wytre w shell skripta:
hello
echo "Weche izleznahte ot funkciqta hello()"
Опитайте се да напишете тази програма и да я стартирате. Единствената цел на функцията hello() е да изпечата съобщение. Функциите естествено могат да изпълняват и по-сложни задачи. В горния пример ние извикахме функцията hello() с този ред:
hello
Когато се изпълнява този ред bash интерпретатора претърсва скрипта за ред който започва с hello(). След което открива този ред и изпълнява съдържанието на функцията.
Функциите винаги се извикват чрез тяхното име. Когато пишете функция можете да започнете функцията с function_name(), както беше направено в горния пример, или да използвате думата function т.е function function_name(). Другият начин, по който можем да започнем нашата функция е function hello():
function hello()
{
echo "Wie ste wyw funkciq hello()"
}
Функциите винаги започват с отваряща и затваряща скоба"()", последвани от отварящи и затварящи къдрави скоби: "{...}". Тези къдрави скоби бележат началото и края на функцията. Всеки ред с код затворен в тези скоби ще бъде изпълнен и ще принадлежи единствено на функцията. Функциите трябва винаги да бъдат дефинирани преди да бъдат извикани. Нека погледнем нашата програма, само че този път ще извикаме функцията преди да е дефинирана:
#!/bin/bash
echo "Izwikwame funkciqta hello()..."
# call the hello() function:
hello
echo "Weche izleznahte ot funkciqta hello()"
# function hello() just prints a message
hello()
{
echo "Wie ste wyw funkciq hello()"
}
Ето какъв е резултатът, когато се опитаме да изпълним програмата:
xconsole$ ./hello.sh
Izwikwame funkciqta hello()...
./hello.sh: hello: command not found
Weche izleznahte ot funkciqta hello()
Както виждате, програмата върна грешка. Ето защо е добре да пишете Вашите функции в началото на скрипта или поне преди си ги извикате. Ето друг пример как да използваме функции:
#!/bin/bash
# admin.sh - administrative tool
# function new_user() creates a new user account
new_user()
{
echo "Preparing to add a new user..."
sleep 2
adduser # run the adduser program
}
echo "1. Add user"
echo "2. Exit"
echo "Enter your choice: "
read choice
case $choice in
1) new_user # call the new_user() function
;;*) exit
;;
esac
За да работи правилно тази програма, трябва да сте влезли като root, тъй като adduser е програма, която само root потребителят има право да изпълнява. Да се надяваме, че този кратък пример Ви е убедил в полезноста на фукциите.
Прихващане на сигнали
Може да използвате вградената команда trap, за да прихващате сигнали във Вашата програма. Това е добър начин да излезете нормално от програмата. Непример, ако имате вървяща програма при натискането на CTRL-C ще изпратите на програмата interrupt сигнал, който ще "убие" програмата. trap ще Ви позволи да прихване този сигнал и ще Ви даде възможност или да продължите с изпълнението на програмата, или да съобщите на потребителя, че програмата спира изпълнението си. trap има следния синтаксис:
trap dejstwie signal
dejstwie указва какво да искате да направите, когато прихванете даден сигнал, а signal е сигналът, който очакваме. Списък със сигналите може да откриете като пишете trap -l. Когато използвате сигнали във вашата шел програма пропуснете първите три букви на сигнала, обикновено те са SIG. Например, ако сигналът за прекъсване е SIGINT, във Вашата шел програма използвайте само INT. Можете да използвате и номера на сигнала. Номерът на сигнала SIGINT е 2. Пробвайте следната програма:
#!/bin/bash
# using the trap command
# da se zipylni funkciqta sorry() pri natiskane na CTRL-C:
trap sorry INT
# function sorry() prints a message
sorry()
{
echo "I'm sorry Dave. I can't do that."
sleep 3
}
# count down from 10 to 1:
for i in 10 9 8 7 6 5 4 3 2 1; do
echo $i seconds until system failure."
sleep 1
done
echo "System failure."
Сега, докато програмата върви и брои числа в обратен ред натиснете CTRL-C. Това ще изпрати сигнал за прекъсване на програмата. Сигналът ще бъде прихванат от trap командата, която ще изпълни sorry() функцията. Можете да накарате trap да игнорира сигнал като поставите "'&#32;'" на мястото на действие. Можете да накарате trap да не прихваща сигнал като използвате "-". Например:
# izpylni sorry() funkciqta kogato programa poluchi signal SIGINT:
trap sorry INT
# nakaraj programata da NE prihwashta SIGINT signala :
trap - INT
# ne prawi nishto kogato se prihwane signal SIGINT:
trap '&#32;' INT
Когато кажете на trap да не прихваща сигнала, то програмата се подчинява на основното действие на сигнал, което в конкретния случай е да прекъсне програмата и да я "убие". Когато укажете trap да не прави нищо при получаване на конкретен сигнал, то програмата ще продължи своето действие, игнорирайки сигнала.
Писане на скриптове за BASH шел : версия 1.2( част 4)
Тази статия е преведена с разрешението на автора и X_console.
Адресът на оригиналната статия е .
Продължениe на [ част 3 ].
AND и OR
Видяхме как се използват условните оператори и колко полезни са те. Има две допълнителни неща, които могат да бъдат добавени. Условните изрази са AND (или "&&") и OR (или "||"). AND условният израз изглежда по следния начин:
условие_1 && условие_2
AND изразът проверява първо най-лявото условие. Ако условието е вярно се проверява второто условие. Ако и то е вярно се изпълнява останалата част от кода на скрипта. Ако условие условие_1 не е вярно(върне резултат false), тогава условие условие_2 няма да бъде проверено. С други думи:
if(ако) условие_1 е вярно, AND(и) if(ако) условие_2 е вярно, then(тогава)...
Ето един пример с AND условие:
#!/bin/bash
x=5
y=10
if [ "$x" -eq 5 ] && [ "$y" -eq 10 ]; then
echo "I dwete uslowiq sa wqrni."
else
echo "Uslowiqta ne sa wqrni."
fi
Тук виждаме, че x и y имат стойността, за която проверяваме. Променете стойноста на x от x=5 на x=12, след което пуснете отново програмата и ще се убедите, че условието не е изпълнено( връща стойност false).
OR изразът е подобен. Единствената разлика е, че проверява дали най-левият израз не е верен(т.е връща резултат false). Ако това е изпълнено се проверява следващия израз и по-следващия:
условие_1 || условие_2
С други думи това звучи така:
if(ако) условие_1 е вярно, OR(или) ако условие_2 е вярно, тогава...
Ето защо кодът след този условен оператор ще бъде изпълнен ако поне едно от условията е вярно:
#!/bin/bash
x=3
y=2
if [ "$x" -eq 5 ] || [ "$y" -eq 2 ]; then
echo "Edno ot uslowiqta e wqrno."
else
echo "Nito edno ot uslowiqta ne e wqrno."
fi
В този пример ще се уверите, че едно от условията е вярно. Сменете стойността на променливата y и изпълнете отново програмата. Ще видите, че нито едно от условията не е вярно.
Ако се замислите, ще видите, че условният оператор if може да замести употребата на AND и OR изразите. Това става чрез използването на вложени if оператори. "Влагане на if оператори" означава да използваме if оператор в тялото на друг if оператор. Можете да правите влагане и на други оператори, а не само на if. Ето един пример с вложени if оператори, които заместват използването на AND израз в кода на програмата:
#!/bin/bash
x=5
y=10
if [ "$x" -eq 5 ]; then
if [ "$y" -eq 10 ]; then
echo "I dwete uslowiq sa wqrni."
else
echo "Uslowiqta ne sa wqrni."
fi
fi
Резултатът е същият, както и ако използвахме AND израз. Проблемът е, че кодът става по-трудно четим и отнема повече време, за да се напише. За да се предпазите от проблеми, използвайте AND и OR изрази.
Използване на аргументи
Може би сте забелязали, че повечето програми в Linux не са интерактивни. От Вас се иска да въведете някакви аргументи; в противен случай получавате съобщение, в което се обяснява как да използвате програмата. Вземете за пример командата more. Ако не напишете име на файл след нея, резултатът ще бъде точно едно такова помощно съобщение. Възможно е да направите вашата шел програма да използва аргументи. За тази цел трябва да използвате специалната променлива "$#". Тази променлива съдържа общия брой на всички аргументи подадени на програмата. Например, ако изпълните следната програма:
xconsole$ foo argument
$# ще има стойност 1, защото има само един аргумент, подаден на програмата. Ако имате два аргумента, тогава $# ще има стойност 2. В допълнение стойността на всеки аргумент (нулевият аргумент е винаги името на програма - foo) може да се вземе като използвате променливите $0 - за името на програмата в случая foo, $1 за стойността на първият аргумент -argument и т.н. Може да имате максимум 9 такива променливи от $0 до $9. Нека да видим това в действие:
#!/bin/bash
# izpechataj pyrwiq argument
# proweri dali ima pone edin argument:
if [ "$#" -ne 1 ]; then
echo "usage: $0 "
fi
echo "Stojnosta na argumenta e $1"
Тази програма очаква един и само един аргумент, за да тръгне. Ако я стартирате без аргументи, или подадете повече от един аргумент, програмата ще изпечата съобщение за това как да се използва. В случай, че имаме само един аргумент шел програмата ще отпечата стойността на аргумента, който сте подали. Припомнете си, че $0 е името на програмата. Ето защо тази специална променлива се използва в "usage" съобщението.
Пренасочване и PIPING
Обикновено, когато стартирате дадена команда, резултатът от изпълнението се отпечатва на екрана. Например:
xconsole$ echo "Hello World"
Hello World
"Пренасочването" Ви позволява да съхраните резултата от изпълнението някъде другаде. В повечето случаи това става към файл. Операторът ">" се използва за пренасочване на изхода. Мислете за него като за стрелка, сочеща къде да отиде резултата. Ето един пример за пренасочване на изхода към файл:
xconsole$ echo "Hello World" > foo.file
xconsole$ cat foo.file
Hello World
Тук резултатът от командата echo "Hello World" е пренасочен към файл с име foo.file. Когато прочетете съдържанието на файла ще видите там резултата. Има един проблем, когато използвате оператора ">". Ако имате файл със същото име, то неговото съдържание няма да бъде запазено, а ще бъде изтрито и заместено с новото. Ами ако искате да добавите информация във файла, без да изтривате старата? Тогава трябва да използвате операторът за добавяне : ">>". Използва се по същия начин с тази разлика, че не изтрива старото съдържание на файла, а го запазва и добавя новото съдържание накрая.
А сега ще ви запознаем с piping. Piping-ът позволява да вземете резултата от изпълнението на дадена програма и да го използвате като входни данни за друга програма. Piping става посредством оператора: "|". Забележете, че това не е малката буквата "L". Този оператор може да получите чрез натискане на клавиша SHIFT и \. Ето и един пример за piping:
xconsole$ cat /etc/passwd | grep xconsole
xconsole:x:1002:100:X_console,,,:/home/xconsole:/bin/bash
Тук четем целия файл /etc/passwd и след това резултатът е подаден за обработка на командата grep, която от своя страна претърсва текста за низа xconsole и изпечатва целия ред, съдържащ този низ на екрана. Може да използвате и пренасочване, за да запишете крайния резултат на файл:
xconsole$ cat /etc/passwd | grep xconsole > foo.file
xconsole$ cat foo.file
xconsole:x:1002:100:X_console,,,:/home/xconsole:/bin/bash
Работи. Файлът /etc/passwd е прочетен и неговото съдържание е претърсено от командата grep за низа xconsole. След което крайният резултат е пренасочен към файл foo.file. Ще откриете, че пренасочване и piping са много полезни средства, когато пишете Вашите шел програми.
Временни файлове
Често ще има моменти, в които ще Ви се наложи да създадете временен файл. Този файл може да съдържа временна информация и просто да работи с някоя програма. В повечето случаи със завършването на изпълнението на програмата се изтрива и временният файл. Когато създадете файл, трябва да му зададете име. Проблемът е, че името на файла, който създавате, не трябва да съществува в директорията, в която го създавате. В противен случай може да затриете важна информация. За да създадете файл с уникално име, трябва да използвате "$$" символа като представка или наставка в името на файла. Вземете за пример следния случай: искате да създадете временен файл с име hello. Има вероятност и някой друг да има файл със същото име в тази директория, което ще доведе до катастрофални резултати за Вашата програма. Ако вместо това създадете файл с име hello.$$ или $$hello, Вие ще създадете уникален файл. Опитайте:
xconsole$ touch hello
xconsole$ ls
hello
xconsole$ touch hello.$$
xconsole$ ls
hello hello.689
Ето го и нашият временен файл.
Връщане на стойности
Повечето програми връщат стойност(и) в зависимост от начина, по който завършват изпълнението си. Например, ако разгледате ръководството на командата grep ще видите, че в него се казва, че командата grep връща стойност 0 ако има съвпадение, и 1 ако не е открито съвпадение. Защо да се грижим да връщаме стойности? По много причини. Нека да кажем, че искате да проверите дали конкретно потребителско име съществува на Вашата система. Единият от начините да направите това е да използвате командата grep върху файла с паролите /etc/passwd. Да предположим, че потребителското име, което търсим е foobar:
xconsole$ grep "foobar" /etc/passwd
xconsole$
Няма никакъв резултат от изпълнението. Това означава че grep не е намерила съвпадение. Но може да направим програмата много по-полезна ако се появява съобщение, което пояснява резултата. Това е, когато искате да проверите стойността, която се връща от дадена програма. Има една специална променлива, която съдържа крайния резултат от изпълнението на програмата. Тази променлива е $?.Разгледайте следния код:
#!/bin/bash
# grep for user foobar and pipe all output to /dev/null:
grep "foobar" /etc/passwd > /dev/null 2>&1
# capture the return value and act accordingly:
if [ "$?" -eq 0 ]; then
echo "Match found."
exit
else
echo "No match found."
fi
Когато стартираме програмата, променливата "$?" ще прихване резултата от командата grep. Ако той е равен на 0, значи има съвпадение и подходящо съобщение ще обяви за това. В противен случай ще изпечата, че няма съвпадения. Това е един основен начин за получаване на резултата, който връща дадена програма. Ще откриете, че доста често ще Ви се наложи да знаете стойността, която връща дадена програма, за да продължите по-нататък.
Ако случайно се чудите какво значи 2>&1, сега ще ви обясня . Под Linux, тези номера обозначават файлови дескриптори. 0 е за стандартния вход (пример: клавиатура), 1 е за стандартния изход (пример: монитор) и 2 е за стандартния изход на грешките (пример: монитор). Всяка обикновена информация се изпраща на файлов дескриптор 1, и ако има грешки те се изпращат на файлов дескриптор 2. Ако не искате тези съобщения да излизат просто можете да ги пренасочите към /dev/null. Забележете, че това няма да спре изпращането на информацията на стандартния изход. Например, ако нямате права да четете от директория на друг потребител, Вие няма да можете да видите нейното съдържание:
xconsole$ ls /root
ls: /root: Permission denied
xconsole$ ls /root 2> /dev/null
xconsole$
Както виждате, съобщението за грешка не беше изпечатано. Същото важи както за други програми, така и за файлов дескриптор 1. Ако не искате резултатът от изпълнението на програмата да се отпечатва на екрана, можете спокойно да го пренасочите към /dev/null. Ако не искате да виждате както резултатът от изпълнението, така и съобщенията за грешка, може да го направите по следния начин:
xconsole$ ls /root > /dev/null 2>&1
Това означава че резултатът от програмата, както и всяка грешка, която предизвика тази програма ще бъдат изпратени на /dev/null, така че никога повече няма да можете да ги видите.
Какво трябва да направите ако искате Вашият шел скрипт да връща стойност при завършване на програмата? Командата exit приема само един аргумент - число, което трябва да се върне при завършване на програмата. Обикновено числото 0 се използва, за да кажем, че програмата е завършила успешно, т.е. не е възникнала никаква грешка по време на нейното изпълнение. Всичко по-голямо или по-малко от 0 обикновено обозначава, че е възникнала някаква грешка. Това го решавате Вие като програмист. Нека проследим следната програма:
#!/bin/bash
if [ -f "/etc/passwd" ]; then
echo "Password file exists."
exit 0
else
echo "No such file."
exit 1
fi
Заключение
С това завършихме увода в bash програмирането. Това ръководство Ви дава основните знания, за да можете да редактирате чужди bash скриптове или да създавате нови. За да постигнете съвършенство обаче, трябва много да практикувате. bash е идеално средство за писане на обикновени административни скриптове. Но за по-големи разработки ще се нуждаете от мощни езици, като C или Perl.