LINUX-BG   Адрес : http://www.linux-bg.org
Писане на скриптове за BASH шел : версия 1.2( част 3)
От: X_console
Публикувана на: 4-05-2000
Адрес на статията: http://www.linux-bg.org/cgi-bin/y/index.pl?page=article&id=advices&key=319145325

Тази статия е преведена с разрешението на автора и X_console.
Адресът на оригиналната статия е http://xfactor.itec.yorku.ca/~xconsole/.

Продължени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 да игнорира сигнал като поставите "''" на мястото на действие. Можете да накарате 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 '' INT

Когато кажете на trap да не прихваща сигнала, то програмата се подчинява на основното действие на сигнал, което в конкретния случай е да прекъсне програмата и да я "убие". Когато укажете trap да не прави нищо при получаване на конкретен сигнал, то програмата ще продължи своето действие, игнорирайки сигнала.

Вижте [ Част 1| Част 2 | Част 3 | Част 4 ]

Тази статия е преведена с разрешението на автора и X_console.
Адресът на оригиналната статия е http://xfactor.itec.yorku.ca/~xconsole/.

Продължени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 да игнорира сигнал като поставите "''" на мястото на действие. Можете да накарате 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 '' INT

Когато кажете на trap да не прихваща сигнала, то програмата се подчинява на основното действие на сигнал, което в конкретния случай е да прекъсне програмата и да я "убие". Когато укажете trap да не прави нищо при получаване на конкретен сигнал, то програмата ще продължи своето действие, игнорирайки сигнала.

Вижте [ Част 1| Част 2 | Част 3 | Част 4 ]


<< Инсталиране на звукова карта ръчно(по-спец. Yamaha 719) | Писане на скриптове за BASH шел : версия 1.2( част 2) >>

Авторите на сайта, както и техните сътрудници запазват авторските права върху собствените си материали публикувани тук, но те са copyleft т.е. могат свободно да бъдат копирани и разпространявани с изискването изрично да се упоменава името на автора, както и да се публикува на видно място, че те са взети от оригиналния им URL-адрес на този сървър (http://www.linux-bg.org). Авторските права на преводните материали принадлежат на техните автори. Ако с публикуването тук на някакъв материал неволно са нарушени нечии права - след констатирането на този факт материалът ще бъде свален.

All trademarks, logos and copyrights mentioned on this site are the property of their respective owners.
Linux is copyright by Linus Torvalds.
© Линукс за българи ЕООД 2007
© Slavei Karadjov 1999 - 2006

All rights reserved.

Изпълнението отне: 0 wallclock secs ( 0.21 usr + 0.02 sys = 0.23 CPU)