Sciptování
Zde je popis regulárních výrazů a scriptovacího jazyka bash
OBSAH
Regulární výrazy
Bash
Regulární výrazy
jsou to znaky které pomáhají definovat skupinu znaků, které mají určité vlasnosti.Díky nim můžeme výběr omezit na slovo na konci řádku, nebo najít slovo, které začíná na m, má 8 znaků a poslední znak je třeba f (smirnoff)
POZOR-shel expanduje znaky, proto je dobrý dát celý výraz do uvozovek viz-
grep telef "( on | ax )" text.txt
[] | jeden z těchto znaků |
[1-4] | znamená čísla 1 až 4 |
[D,Z] | znamená písmena D a Z |
[123] | Množina číslic 1, 2 a 3. |
b[au]f | Odpovídá řetězci baf nebo buf. |
[a-zA-Z] nebo [\w | ] Množina rozsahu znaků. Odpovídá jednomu výskytu písmene
A až Z (malá i velká písmena,
pouze bez diakritiky). |
[[:alpha:]] | Totéž, ale zahrnuje i písmena s háčky a čárkami
(pokud jsou nastavené české locales). |
[[:alnum:]] | Jako předchozí, ale navíc zahrnuje číslice. |
[0-9] nebo [[:digit:]] nebo [\d] | Množina všech číslic. |
[^0-9] nebo [^[:digit:]] nebo [^\d] nebo [\D] | Odpovídá jednomu znaku, který není číslice |
[[:space:]] | Množina "whitespace" znaků |
() | gruping, neboli co je v této závorce se bude brát jako jeden řetězec |
(ahoj|cau) | znamená slovo ahoj nebo cau |
| | nebo |
^ | označuje začátek řádku |
$ | označuje konec řádku |
\< | začátek slova |
\> | konec slova |
.. (2x tečka) | označuje nasledujíci metacharakter ( třeba ,[,] ) |
. (1x tečka) | Množina všech znaků. Odpovídá jednomu znaku. |
* | označuje vyskyt 0 až nekonečně jakéhokoliv znaku |
+ | označuje výskyt aspon 1x až nekonečně |
? | označuje výskyt 1 nebo 0 |
{n} "" "" | označuje výskyt prave n-krat |
{n,} "" "" | označuje výskyt nejméně n-krat |
{n,m} "" "" | označuje výskyt nejméně n-krat, nejvice m-krat |
\t | tabulátor |
\n | nový řádek |
\. | Odpovídá tečce. |
\\ | Odpovídá zpětnému lomítku. |
\* | Odpovídá hvězdičce. |
Bash
instalace
/usr/ports/shells/bash
make install
nastaveni bashe jako vychozi shell
chsh -s /usr/local/bin/bash user
cesta ke shelu bash
#!/usr/local/bin/bash
pripadne udelat zastupce pro spouštění bash scriptů bez úpravy hlavičky
ln -s /usr/local/bin/bash /bin/bash
můžeme se z aktuálního shelu přepnout do bashe třeba jen na chvíli,udělat co potřebujem a vrátit se zpět
přepnutí do bash
bash
zpět
exit
přepnutí do sh
sh
zpět
return
jednoduchý příkazy
> presmerovani vystupu
ps > text.txt
< vlozeni do programu
mysql < zaloha.sql
>> pripoji vystup na konec souboru
ps >> text.txt
2 > &1 nasmerovani dvou vystupu do jednoho souboru
kill -l 1234 > kill.txt 2 > &1
vstup (stdin (0) ) a výstup (stdout (1) ) jsou přesměrovány do jednoho výstupu
vstup může být příkaz zadaný z klávesnice, nebo výsledek jiného procesu
výstup je většinou výsledek příkazu či procesu, zobrazený na obrazovce, vytištěný na tiskárně, uložený do souboru nebo předaný dalšímu procesu ke zpracování
chybový výstup (stderr (2) )-do tohoto výstupu jdou chyby, nechá se přesměrovat třeba do souboru, nebo využít v podmínkách
/dev/null přesměrovaní pro smazani výstupu,nebo smazani souboru
kill -l 1234 > /dev/null
soubor.txt > /dev/null
| roura /pipe ,předáva výsledek programu jinému programu
ps -ax | more
#!/bin/sh začátek každého scriptu
# komentar
testtestování na podmínky
if test -f /etc/foo
se dá také zapsat takto:
if [ -f /etc/foo ]; then
Možnosti příkazu test
testy souborů/adresářů
-e | soubor existuje |
-f | soubor je standardní (tzn. není to ani adresář ani speciální soubor) |
-s | soubor má nenulovou velikost |
-d | soubor je adresář |
-b | soubor je speciální blokové zařízení |
-c | soubor je speciální znakové zařízení |
-p | soubor je roura (pipe) |
-h | soubor je symbolický link |
-L | soubor je symbolický link |
-S | soubor je socket |
-t | soubor je deskriptor |
-r | soubor má práva pro čtení (pro uživatele, který spustil daný test) |
-w | soubor má právo zápisu (pro uživatele, který spustil daný test) |
-x | soubor je spustitelný (pro uživatele, který spustil daný test) |
-g | soubor má nastaven SGID bit |
-u | soubor má nastaven SUID bit |
-k | soubor má nastaven sticky bit |
-O | jsme vlastníkem souboru |
-G | group ID souboru je stejná jako naše |
-N | soubor byl modifikován od posledního načtení |
f1 -nt f2 soubor | f1 je novější než soubor f2 |
f1 -ot f2 soubor | f1 je starší než soubor f2 |
f1 -ef f2 soubor | f1 a f2 je hard link na jeden a tentýž soubor |
! | obrací logiku testů |
#####################
IFS='' #interni oddělovač poli{jakym znakem budou oddeleny jednotlive pole-uzavírá se do apostrofů-zde je to mezera}
set A B C #nastaveni parametru/poli
echo $@ #volaní fce echo
ABC #výsledek
unset IFS #zrusení IFS
echo $@ #volaní fce echo
A B C #výsledek
########################
Proměnné
proměnnou může být číslo, slovo, výraz, případně i příkaz nebo jiná proměnná
POZOR-u přiřazení promenna=hodnota nesmí být u rovnítka mezera
proměnnou definujeme názvem a hodnotou
nazev=hodnota
proměnnou voláme tak, že před název proměnné dáme znak $
příklad
cislo=5
den="patek"
datum=`date "+%Y-%m-%d" ` # pozor -příkazy uzavíráme do ``(na angl klávesnici pod ESC)
date=$datum
volání proměnné
echo $datum
zvláštním případem jsou systémové proměnné
$? - obsahuje návratový kód posledního procesu spuštěného na popředí.
$$ - obsahuje pid aktuálního procesu (ať víte co zabíjet :-)
$0 - obsahuje jméno právě prováděného skriptu: mujskript
$1 - obsahuje první argument, předaný skriptu, na příkazové řádce: parametr1
$9 - obsahuje 9-tý argument z příkazové řádky: parametr9
$* - obsahuje všechny argumenty volání programu (jako jedno slovo): parametr1 parametr2 ... parametrn
$@ - obsahuje všechny argumenty volání programu (jednotlivá slova): parametr1 parametr2 ... parametrn
$# - obsahuje počet argumentů z příkazové řádky (v našem případě n).
dalšími proměnnými je systémové prostředí
Vypíšeme jej příkazem
set
Výpis proměnných v bashi
BASH=/bin/bash
BASH_ARGC=()
BASH_ARGV=()
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="3" [1]="2" [2]="39" [3]="1" [4]="release" [5]="i386-portbld-freebsd6.3")
BASH_VERSION='3.2.39(1)-release'
BLOCKSIZE=K
COLUMNS=106
DIRSTACK=()
EDITOR=vi
ENV=/home/votruba/.shrc
EUID=0
FTP_PASSIVE_MODE=YES
GROUP=wheel
GROUPS=()
HISTFILE=/root/.bash_history
HISTFILESIZE=500
HISTSIZE=500
HOME=/root
HOST=test63.keytec.cz
HOSTNAME=test63.keytec.cz
HOSTTYPE=FreeBSD
IFS=$' \t\n'
LINES=63
LOGNAME=votruba
MACHTYPE=i386
MAIL=/var/mail/votruba
MAILCHECK=60
MC_SID=32322
MC_TMPDIR=/tmp/mc-root
OPTERR=1
OPTIND=1
OSTYPE=FreeBSD
PAGER=more
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin:/root/bin
PPID=32322
PS1='[\u@\h \w]\$ '
PS2='> '
PS4='+ '
PWD=/root/script
REMOTEHOST=192.168.0.92
SHELL=/bin/csh
SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
SHLVL=3
SSH_CLIENT='192.168.0.92 1234 22'
SSH_CONNECTION='192.168.0.92 1234 192.168.0.5 22'
SSH_TTY=/dev/ttyp0
TERM=xterm
UID=0
USER=votruba
VENDOR=intel
_=bash
proměnné můžeme i vymazat
zapomene všechny proměnné
unset
zapomene proměnnou date
unset date
přidání proměnné nastálo
export PROMENNA=nova_promenna
přidání nové cesty do proměnné PATH
export PATH=$PATH:/dalsi/cesta/kde_hledat
Pole
Obsahem pole může být i jiné pole
pole můžeme naplnit 2mi způsoby
nadefinování pole
declare -a cesta
cesta[1]=path
cesta[2]=path2
cesta[3]=path3
cesta[4]=path4
cesta[5]=path5
cesta[6]=path6
cesta[7]=path7
cesta[8]=path8
nadefinování pole - druhá možnost
pole=( jedna dva tri ctyri pet )
v tomto případě má první položka pozici 0. Tj slovo "pet" ma pozici 4
echo ${pole[*]:0}
výsledek
jedna dva tri ctyri pet
výpis všech položek pole
echo ${cesta[*]} #NEBO ${pole[*]:0}
výsledek
path path2 path3 path4 path5 path6 path7 path8
výpis jedné položky pole
echo "${cesta[4]}"
výsledek
path4
výpis všech položek pole od daného čísla do konce(zde od 3)
echo "${cesta[*]:3}"
výsledek
path3 path4 path5 path6 path7 path8
výpis všech položek pole od daného čísla a k němu 2 následující
echo "${cesta[*]:3:2}"
výsledek
path3 path4
výpis všech položek pole s vynecháním nějaké položky ( zde definované reg. výrazem)
echo "${cesta[*]#*3}"
výsledek
path path2 path4 path5 path6 path7 path8
If #testuje podminky
if jestliže
PODMINKA
then potom proved´
PRIKAZY
else jesliže nevyhovi,pak proved
PRIKAZY
fi ukonceni
#####################
Elif #stejně jako IF ,ale pokud neni splněna prvni podmínka testuje druhou
if jestliže
PODMINKA
then potom proved´
PRIKAZY
elif nebo proved´
PRIKAZY
else jesliže nevyhoví,pak proved´
PRIKAZY
fi ukončeni
POZOR-v podmínce if [ vyraz ] musí být testovaný výraz oddělen mezerou od závorek [ ]
######################
For #vytvářeni cyklu ktere pracují s rozsahem hodnot-mohou být uvedeny v programu,nebo jako parametry názvu scriptu
for PROMENNA in HODNOTY
pro kazdou promennou{promenna je to co je vyjadreno za IN,byva to nekolik hodnot oddelenych mezerou}
do proved´
PRIKAZY
done ukončeni
for DNY in PO UT ST CT PA SO NE
do
echo $DNY
done
PO
UT
ST.....
zde DNY jsou proměnnou a to co je za in (oddělené mezerami) je počet rotací
je možné na místě proměnné nadefinovat i pole
for inkr in ${uzivatel[*]}
do
......
v tomto případě cyklus bude rotovat tolikrát, kolik je v poli objektů. Pozor, pokud bude pole s 5 objekty a jednim z objektů bude další pole s 2mi položkami
tak cyklus prorotuje 2(to vložené pole) + 4(zbytek objektů) tj 6x.
Klidně můžeme použít pro počet rotací nějaké pole, nebo výraz a v příkaze "do" provádět akci, která nemá s tím polem nic společného jen si z něj bere počet rotací.
našel jsem hezký příklad, kdy si příkaz v aktualním adresáři zjistí soubory .htm a následně je je přejmenuje na .html
for file in *.htm
do
echo "menim pripony .htm souboru $file... na .html"
mv $file.htm $file.html
done
Příkaz for se nechá použít i bez "in HODNOTA", pak se počet rotací zadá výrazem
např.
for (( a=1 ; $a-4 ; a=$a+1 ))
do echo $a
done
######################
While #prikaz ktery provadi prikaz pokud JE splnena podminka
while PODMINKA
do
PRIKAZY
done
V následujícím příkladu použijeme proměnnou x, která bude při každém průchodu cyklu zvyšovat svojí hodnotu a to až do té doby než dosáhne hodnoty 10.
#!/bin/bash
x=0; # inicializuje hodnotu x na 0
while [ $x -le 10 ]; do
echo "Aktuální hodnota x: $x"
x=$(expr $x + 1) # zvýšení hodnoty x o 1
sleep 1
done
Jak vidíte, používáme příkaz test (hranaté závorky), abychom zjistili, jestli hodnota proměnné x je menší nebo rovno 10. Je-li menší nebo rovno 10, test je vyhodnoceno jako true a blok příkazů za slovem do se může provést. Je-li však podmínka vyhodnocena jako false, pokračuje program v běhu za slovem done.
########################
Until #prikaz ktery provadi prikaz pokud NENI splnena podminka
until PODMINKA
do
PRIKAZY
done
#!/bin/bash
x=0
until [ "$x" -ge 10 ]; then
echo "Aktuální hodnota x: $x"
x=$(expr $x + 1)
sleep 1
done
Je použita struktura until a tedy příkaz test je upraven tak, aby byla struktura ukončena bude-li hodnota proměnné x větší nebo rovno 10. Znamená to tedy, že se vypíší hodnoty pouze od 0 do 9.
########################
Case #struktura case je určena pro vykonání jednoho z několika kusů kódu a to podle toho, jakou hodnotu má proměnná uvedená za příkazem case
case PROMENNA in
vzorek [ vzorek| vzorek] ....) PRIKAZY;; #kazdy vzorek musi byt ukoncen 2ma stredniky
vzorek [ | vzorek] ....) PRIKAZY;; # mezi vzorky je mozno vkladat vice prikazu
vzorek [ | vzorek] ....) PRIKAZY;;
...........
esac
#!/bin/bash
echo "Je nyní ráno? Odpovězte \"ano\" nebo \"ne\""
read timeofday # nacte uzivatelsky vstup
case "$timeofday" in #nacteni promenny
ano | a | Ano | ANO ) #pokud je kladna odpoved
echo "Dobré ráno" #vykona tento prikaz
;;
[nN]* ) #pokud je zaporna odpoved
echo "Dobré odpoledne" #vykona tento prikaz
;;
* ) #pokud je jina odpoved
echo "Promiňte, ale nerozuměl jsem" #vykona tento prikaz
echo "Odpovězte \"ano\" nebo \"ne\"" #vykona tento prikaz
exit 1
;;
esac #ukonceni prikazu
exit 0
########################
Seznamy
&& #logicke ANO-spojovani prikazu,nasledujici
pokracuje jen po uspesnem vykonani predchazejiciho
#jinak skonci
PRIKAZ1 && PRIKAZ2 && PRIKAZ3 && PRIKAZ4 cd /root && touch test.sh && cp test.sh test2.sh
|| # logiske NEBO- prikaz jede z prava do leva
dokud nektery z prikazu nevrati hodnoutu TRUE,pak skonci
PRIKAZ1 || PRIKAZ2 || PRIKAZ3 || PRIKAZ4
#!/bin/bash
rm -f file_one
if [ -f file_one ] || echo "hello" || echo "there"
then
echo -e "in if"
else
echo -e "in else"
fi
exit 0
Výstup programu bude následující:
xconsole$ ./skript.sh
hello
in if
########################
Funkce #Použití funkcí se vyplatí v případě, kdy se bloky kódu ve skriptu opakují.
function NAZEV_FUNKCE () #slovo *function* muzeme vynechat
{
PRIKAZY
}
NAZEV_FUNKCE #funkci zavolame zadanim jejiho nazvu-musi
byt deklarovana pred zavolanim
#!/bin/bash
yes_or_no() {
echo "Je tvé jméno $* ?"
while true
do
echo -n "Napiš ano nebo ne: "
read x
case "$x" in
a | ano ) return 0;;
n | ne ) return 1;;
* ) echo "Napiš ano nebo ne"
esac
done
}
echo "Původní parametr je $*"
if yes_or_no "$1"
then
echo "Ahoj $1, pěkné jméno"
else
echo "Nikdy"
fi
exit 0
prispusteni tothoto scriptu se musi jako parametr zadat jmeno
Tento příklad funguje tak, že po spuštění skriptu je definována funkce yes_or_no, ale není provedena. V příkazu if provede skript funkci yes_or_no, které předá jako parametry zbytek řádku, kde zápis $1 nahradí prvním parametrem skriptu. Funkce pak pracuje s těmito parametry, které jsou nyní uloženy v pozičních proměnných $1, $2 atd. a vrátí hodnotu volajícímu příkazu. Příkaz if v závislosti na návratové hodnotě provede příslušní příkaz.
###################################
Příkazy
break #slouží k odskoku z cyklu for,
while nebo until ještě před splněním řídicí podmínky nepouziva se
##
: #zastupuje hodnotu true
rm -rf fred
if [ -f fred ]; then
:
else
echo "Soubor fred neexistuje."
fi
##
continue #tento příkaz spustí další iteraci (průchod)
cyklů for, while nebo until, přičemž je proměnné cyklu přiřazena další hodnota ze seznamu
#!/bin/bash
rm -rf fred*
echo > fred1
echo > fred2
mkdir fred 3
echo > fred4
for file in fred*
do
if [ -d "$file" ]; then
echo "přeskakuji adresář $file"
continue
fi
echo soubor je $file
done
rm -rf fred*
exit 0
##
. nebo
Source #nacte externi soubor,vykona jej a vysledek vrati puvodnimu scriptu
##
eval #umožňuje vyhodnocovat argumenty
foo=10
x=foo
y='$'$x
echo $y
Tento skript vrátí $foo, ale následující
foo=10
x=foo
eval y='$'$x
echo $y
již vrátí 10. Tudíž příkaz eval funguje trochu jako další znak $ - vrátí hodnotu hodnoty proměnné.
##
exec # nahradí současný proces zadaným příkazem.
exec wall "Děkuji za všechny ryby"
ve skriptu nahradí aktuální shell příkazen wall. Řádky, které ve skriptu následují po příkazu exec, nebudou provedeny, protže shell, který skript prováděl, již neexistuje.
##
exit #ukončení skriptu s návratovým kódem n
exit 0 #navratova hodnota TRUE
exit 1 #navratova hodnota FALSE POKUD SE POUZIJE NEKDE VE SCRIPTU-SCRIPT SE UKONCI A DAL NEJEDE
##