Упатство:Програмирање во Bash

Од Сподели wiki
Прејди на прегледникот Прејди на пребарувањето

За да продолжите со читање на ова упатсво, строго препорачуваме да ги имате основните знаења за Bash школката и основните команди за таа школка. Основно познавање на GNU/Linux како оперативен систем. Пожелно е и некое искуство со програмски јазици. Иако ова упатство не е увод во програмирање, сепак опфаќа некои основни концепти.

Креирање едноставни скрипти

Традиционалната hello world скрипта

#!/bin/bash 
echo Hello World

Оваа скрипта е составена од 2 линии код. Првата линија ни објаснува која програма системот да ја користи за да ја стартува датотеката.

Втората линија е единствената акција изведена од скриптата, која го принта текстот 'Hello world' на вашиот терминал. Ако добиете нешто слично како ./hello.sh:Command not found, тогаш најверојатно имате грешка во првата линија

'#!/bin/bash'. Побарајте со 'whereis bash' или погледнете во делот 'Барајќи го bash' за да видите како точно да ја напишете оваа линија код.

Едноставна скрипта за бекап

#!/bin/bash 
tar -cZf /var/my-backup.tgz /home/me/

Во оваа скрипта наместо испринтана порака на терминалот, ние креираме tar-ball од ’home’ корисничкиот директориум. Оваа скрипта не е баш наменета за употреба, подобра и покорисна бекап скрипта ќе биде презентирана подоцна во овој документ.

Пренасочување

Теорија и краток преглед

Постојат 3 опишувачи на датотеки, stdin, stdout и stderr (std=стандард).

Во основа можете:

  1. да го пренасочите stdout во некоја датотека
  2. да го пренасочите stderr во некоја датотека
  3. да го пренасочите stdout во stderr
  4. да го пренасочите stderr во stdout
  5. да ги пренасочите stderr и stdout во некоја датотека
  6. да ги пренасочите stderr и stdout во stdout
  7. да ги пренасочите stderr и stdout во stderr

1 претстатува stdout (стандарден излез) и 2 stderr (стандарден излез за грешки).

Мала забелешка околу овие работи: со наредбата less можете да ги видите и двата stdout(кој останува во баферот) и stderr кој ќе биде испечатен на екранот, но избришан доколку се обидете да го прелистувате или прегледувате баферот.

Пример: stdout во датотека

Овој пример ќе предизвика излезот од програмот на екранот да биде запишан во некоја датотека.

ls -l > ls.l.txt

Овде, датотеката со име 'ls.l.txt' ќе биде креирана и ќе биде составена од она што го гледате на екранот која ја куцате и извршувате наредбата 'ls -l'.

stderr во датотека

Овој пример ќе предизвика stderr излезот од програмот да биде запишан во датотека.

grep da * 2> grep-errors.txt

Овде, датотеката со име 'grep-errors.txt' ќе биде креирана и ќе биде составена од stderr делот од излезот при извршувањето на 'grep da *' наредбата.

stdout кон stderr

Овој пример ќе предизвика stderr излезот од програмот да биде запишан во истиот покажувач на датотеки него stdout.

grep da * 1>&2 

Овде, stdout делот од наредбата е испратен до stderr, можете да го забележите тоа на најразлични начини.

Пример: stderr кон stdout

Овој пример ќе предизвика stderr излезот од програмот да биде запишан во истиот покажувач на датотеки него stdout.

grep * 2>&1

Овде, stderr делот од наредбата е испратен до stdout, ако ставите pipe до less, ќе видите дека линиите кои нормално 'исчезнуваат'(кои што се запишани во stderr) се зачувани сега (затоа што тие се во stdout).

stderr и stdout до датотека

Овој пример ќе го смести секој излез од програмот во некоја датотека. Ова е згодно понекогаш, бидејќи може да се комбинира со cron, ако сакаме наредбата да помине во апсолутна тишина.

rm -f  $(find / -name core) &> /dev/null

Ова (размислувајќи за запишувањето во cron) ќе ја избрише секоја датотека со име 'core' во било кој директориум. Најважно е да бидете сигурни што прави оваа наредба, доколку сакате да го избришете нејзиниот излез.

Протоци (pipes)

Ова поглавје ја објаснува на практичен начин како да користите протоци и зошто би сакале да ги употребувате баш нив.

Која е улогата на протоци, и зошто би ги користел

протоците дозволуваат да се користи излезот на некоја програма како влез на некоја друга.

Протоци и sed

Ова е најобичен начин на користење на протоците.

# ls -l | sed -e "s/[aeio]/u/g"

Еве што се случува овде: Прво наредбата ls -l се извршува, и нејзиниот излез наместо да биде испринтан на екран, е испратен (преку проток) до sad програмот, кој што принта тоа што мора.

Алтернатива до ls -l*.txt

Најверојатно, ова е потешкиот начин да се направи ls -l*.txt, но овде ќе го користите за да ги илустрираме протоците, а не да решаваме некоја дилема

# ls -l | grep "\.txt$"

Овде, излезот од програмата ls -l е испратен преку grep програмата, кој по редослед ќе ги испринта линиите кои одговараат со "\.txt$".

Променливи ($)

Променливите се користат во сите програмски јазици. Нема типови на податоци. Променливата во беш (bash) може да биде број, карактер или низа од карактери. Нема потреба од декларација на променливата, таа ќе се креира само со доделувањето на вредност на нејзината референца.

Hello World! со променливи

#!/bin/bash 
STR="Hello World!"
echo $STR

Втората линија, креира променлива со име STR и е иницијализирана со стрингот 'Hello World' кадешто вредноста на оваа променлива се надополнува со знакот '$'на почетокот.Важно е дека ако не се стави '$' знакот пред променливата, тогаш излезот од програмата ќе биде друг, сигурно не на оној начин на којшто посакуваме да работи.

Проста скрипта за бекап 2

#!/bin/bash 
OF=/var/my-backup-$(date +%Y%m%d).tgz
tar -cZf $OF /home/me/

Скриптата не запознава со друго нешто. Најпрво од се, треба да бидеме запознаени со декларацијата и иницијализацијата на променливите во вториот ред од кодот. Забележи го изразот '$(date +%Y%m%d)'. Ако ја извршите оваа скрипта ќе забележите дека ги извршува командите внатре во заградите, прикажувајќи го излезот од нив. Забележете дека во оваа скрипта, името на излезната датотека ќе биде различно секој ден врз основа на промената на форматот од date наредбата (+%Y%m%d). Ова можете да го промените со додавање на друг формат.

Локални променливи

Локалните променливи можат да бидат креирани со користење на клучниот збор 'local'

 #!/bin/bash
 HELLO=Hello 
 function hello {
 local HELLO=World
 echo $HELLO
 }
 echo $HELLO
 hello
 echo $HELLO

Овој пример би требало да биде доволен, за да покаже како се користат локалните променливи.

Услови

Условите ни даваат за предност да одлучиме дали да се изврши некоја акција, или не, оваа одлука е земена со евалуирање на изразот.

Малку теорија

Условите имаат многу форми. Најпростата форма е: 
if израз then наредба,

каде што наредбата ќе биде извршена само ако условот евалуира во точно пошто е од тип bool.'2<1' е израз кој евалуира во неточно, додека '2>1' евалуира во точно.Условите имаат и други форми како на пример: if израз then наредба1 else наредба2 . Кадешто наредба1 ќе биде извршена само ако изразот евалуира во точно, инаку наредба2 ќе биде извршена. Друга форма на формирање на услови е:

 if израз1 then
     наредба1 
 else if израз2 then
     наредба2
 else наредба3

Во оваа форма е додаден само „ELSE IF 'израз2' THEN 'наредба2', која прави наредба2 да биде извршена само ако израз2 евалуира во точно.

Околу синтаксата:

Основната форма за 'if' конструкцијата во bash е следнава:

 if [израз]; 
 then 
 код ако if 'изразот' е точен. 
 fi 

Основен пример за услов

if-then

 #!/bin/bash
 if [ "foo" = "foo" ]; then
 echo expression evaluated as true
 fi

Кодот ќе биде извршен ако изразот во големите загради е точен и се најде после клучниот збор 'then' и пред 'fi' којшто означува крај на кодот што се извршил по обработката на условот.

Основен пример за услов 2

if-then-else

 #!/bin/bash
 if [ "foo" = "foo" ]; then
 echo expression evaluated as true
 else
 echo expression evaluated as false
 fi

Услови со променливи

 #!/bin/bash
 T1="foo"
 T2="bar"
 if [ "$T1" = "$T2" ]; then
 echo expression evaluated as true
 else
 echo expression evaluated as false
 fi

Циклуси

  1. for циклусот е малку различен од другите програмски јазици. Дозволува итерации преку серии од зборови без употреба на низи.
  2. while извршува парче код ако контролниот израз е точен, и запира кога изразот ќе евалуира во неточно (or a explicit break is found within the executed code.)
  3. until е речиси ист со while (додека) циклусот, освен тоа што кодот се извршува додека контролниот израз евалуира во неточно.

Пример

#!/bin/bash
for i in $( ls ); do
echo item: $i
done

Во вториот ред ние декларираме променливата да прими вредности од $(ls).Во третиот ред може да биде и подолг по потреба, или да има повеќе линии пред done. 'done' индицира дека кодот што ја користи вредноста на $i е завршен, и $i може да прими нова вредност.

for циклус во C/Perl стил

 #!/bin/bash
 for i in `seq 1 10`;
 do
 echo $i
 done

Пример за while циклус

 #!/bin/bash 
 COUNTER=0
 while [ $COUNTER -lt 10 ]; do
 echo The counter is $COUNTER
 let COUNTER=COUNTER+1 
 done

Оваа скрипта ’се такмичи’ со добро познатата (C, Pascal, perl, итн) 'for' структура.

= Пример за until циклус

 #!/bin/bash 
 COUNTER=20
 until [ $COUNTER -lt 10 ]; do
 echo COUNTER $COUNTER
 let COUNTER-=1
 done