Тази статия е преведена с разрешението на автора и X_console.
Адресът на оригиналната статия е http://xfactor.itec.yorku.ca/~xconsole/.
Продължени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
Вижте [ Част 1|
Част 2 |
Част 3 |
Част 4
]