Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: webhope 31. 03. 2010, 19:49:16
-
Pokouším se zjistit jestli je možné udělat následující:
V prvním příkladu, který funguje mám strukturu příkazů takovouto:
select polozka in A B C; do prikazova_cast; done;
Čili vyberu si něco ze seznamu a pak se provede cyklus s příkazy. Tohle mohu opakovat libovolně-krát, protože je to uvnitř while cyklu, a když chci skončit, tak ukončím cyklus while.
A teď mám druhou situaci.
Příkazová část uvnitř do.. done; zůstává skoro stejná, až na to, že vše chci provést automaticky, místo ručně. Nechci ale kopírovat dlouhý příkazový blok, raději bych použil stejný cyklus. Problém je v tom, že se potřebuji v této situaci zbavit toho selectu.
Zkoušel jsem něco takového, ale asi to nemá správnou syntaxi:
automate=0
# automate=1
echo; echo 'Vyberte';
if [ "$automate" == "0" ]; then
select hledam in 'A' 'B' 'C';
fi;
do
echo $automate
break;
done;
Výsledek:
# if [ "$automate" == "0" ]; then
> select hledam in 'A' 'B' 'C';
> fi;
bash: chyba syntaxe poblíž neočekávaného tokenu „fi“
# do
bash: chyba syntaxe poblíž neočekávaného tokenu „do“
# echo $automate
0
# break;
bash: break: má smysl jen ve smyčkách „for“, „while“ nebo „until“
# done;
bash: chyba syntaxe poblíž neočekávaného tokenu „done“
-
Ještě jsem zkoušel tohle řešení (předdefinovat vstup pro select), ale buď to dělám blbě nebo to nejde:
i=$((i+1));
( [ "$automate" == "0" ] && select item in 'A' 'B' 'C' <$i ) || ( [ "$automate" == "1" ] && select item in 'A' 'B' 'C' );
do
echo $automate
break
-
Nechci ale kopírovat dlouhý příkazový blok
Na to sa pouzivaju funkcie
function OpakujuciSaCyklus {
#opakujuci sa kod
}
if [ "$automate" -eq 0 ]
then
select a in A B C
do
OpakujuciSaCyklus
done
else
OpakujuciSaCyklus
fi
-
Pomocí funkce bych to řešit uměl, ale jde o to, že předělávat několik příkazových bloků a dalších cyklů do funkce se mi nezdá efektivní ani dost přehledné. Bylo by to dost náročné předělat to celé do funkce. Jednodušší řešení asi bude pro mě pouze částečná automatizace.
Při podmínce pokud je pravda, přepíšu pole pro výběr např.
select item in "Opravdu zpracovat tuto položku?" "Ne"
Přitom původní pole obsahuje delší seznam. Zde při tom zautomatizování použiju i=$((i+1)) abych získal z předdefinovaného pole aktuální položku. Takže zpracuju celé pole (všechny položky) uvnitř cyklu while, uživatel ale bude muset potvrdit nebo odmítnout cca 18 položek.
-
Pak nemusíš psát funkci pro tělo toho cyklu, ale pro jeho podmínku.
function getdalsi { dalsi=automaticky vyber nebo select}
while getdalsi; do ...
-
To nevím jak to myslíš. Moc stručné. Nepochopil jsem zpracování argumentů funkce a kde má být done;
-
Myslel jsem tím to, že ten select ...; do ...; done můžeš jednoduše upravit třeba na while funkce ...; do ...; done a dopsat jen drobnou funkci, která podle potřeby vybere selectem nebo automaticky.
-
Jediné co mě napadlo je toto:
test(){ if [ "$automate" == "1" ]; then return true; else return false; fi; }
i=$((i+1));
test() || select item in 'A' 'B' 'C' ;
do
echo $automate
break
done;
Mělo by to dělat toto.
Pokud je $automate==1, tak se provede funkce a vrátí true, takže select se přeskočí, ale cyklus se provede.
Pokud je $automate==0, tak se provede funkce a vrátí false, takže select se provede a cyklus se provede.
Hlásí to stejnou chybu:
bash: chyba syntaxe poblíž neočekávaného tokenu „||“
Hlavní pro mě je, abych ty bloky v cyklu nemusel strkat do funkce. V prvním případě se select nemá provést, ve druhém ano.
-
Neviem či som vás správne pochopil ale mohli by ste si buď spraviť vlastný "select" alebo, za predpokladu že skupina príkazov prikazova_cast pracuje buď z defaultnou hodnotou a je vynechany užívateľský vstup ( automate=1 ) alebo z hodnotou vybratou užívateľom ( automate=0 ) by to mozno islo aj takto:
REP="default value"
if [ "$AUTOMATE" == "0" ]; then
select item in 'A' 'B' 'C' ; do
REP=$item
break
done
fi
echo $REP
-
Ale měl jsem chybnou syntaxi v tom starém kodu proto, mi to nefungovalo. Kód dole funguje, ale musím ještě vymyslet, jak dořešit, aby cyklus fungoval i při volání té funkce test (select=0)! Asi nemohou rekurzivně volat test a při tom spouštět cyklus...
Poznámka: přejmenoval jsem název proměnné $automate na $select. Pokud je $select==1 použije se select a spustí cyklus. Pokud je $select==0 spustí se cyklus, aniž by se aktivoval select.
test(){
if [ "$select" == "1" ]; then return 1; else return 0; fi;
}
select=0;
pole=('A' 'B' 'C')
i=$((i+1));
test || select item in "${pole[@]}";
do
echo $i
done;
EDIT:
No jo, jenže největší problém je v tom, že ten cyklus do.. while je nejspíš součástí toho select. Asi jako if [...]; then ...; fi; Čili, ten cyklus patří k tomu selectu, ne k té funkce test. Když na začátku podmínky s testem vyjde, že nemá provádět select, tak neprovede ani ten cyklus. Čili řešení situace nevidím.
-
Ak som spravne pochopil myslienku, tak by to mohlo vyzerat takto:
function test {
if [ "$1" == "N" ]
then
if [ -z "$volba" ]
then
volba="automation"
return 0
else
return 1
fi
fi
PS3="Vyber si (zly vyber ukonci cyklus): "
select volba in A B C
do
[ -z "$volba" ] && return 1 || return 0
done
}
selection="N"; #"Y"
volba=""
while test $selection
do
echo "Vybrate: $volba"
done
Ak je v premennej selection retazec "N", tak sa raz spusti cyklus a premenna volba obsahuje "automation". Inak sa spusti cyklus podla vyberu zo selectu. Zly vyber v selecte ukonci cely cyklus while.
-
Ta ista otazka sa nepise do dvoch roznych tem (http://forum.root.cz/index.php?topic=307.msg1351#msg1351)!!!
-
Tak jsem aplikoval celou strukturu jak si doporučil a už to funguje až na jednu poslední věc:
while get_device || [ "$continue" == "1" ] ; do # Funkce "get_device $automate" rozhoduje o tom zda se provede select
echo ; echo POKRACOVANI:$continue; echo
done;
Funkci jsem pojmenoval get_device.
Když se zpravují všechna zařízení, tak vracím (oprava: nastavuji) continue=0; přesto se ale cyklus neukončí a je tam výstup:
POKRACOVANI:0
Takže zkouším [[ "$continue" == "1" ]] a [[ $continue -eq 1 ]] ale výraz je vyhodnocen pozitivně. Takže si v klidu pokračuje dál :-(
Edit:
Jo a funkce vraci 0.
-
tak vracím continue=0
Co si ty myslel? Kde sa nastavuje premenna continue?? Funkcia vracia hodnotu pomocou return, spracuje sa len cez nazov funkcie (zavola ju a vrati vysledok).
Cyklus bude pokracovat ak get_device vrati nenulovu hodnotu alebo continue je jedna. Nechcel si tam mozno "a zaroven" namiesto "alebo"?
-
Nesprávně jsem se vyjádřil. Ve funkci nastavuji proměnnou continue.
Funguje to takto:
V té funkci zpracovávám pole - seznam zařízení a přípojných bodů.
Počítám cykly. Dokud se nejedná o poslední cyklus $i==$count tak se nastavuje continue=1 a funkce vrací 1. Když je počet cyklů $i==$count tak nastavuji continue=0 a vracím 0;
Teď nevím proč to tak, je ale jinak to nešlo, je to složitější s těma cyklama. Každopádně, stoprocentně vím, že funkce mi u poslední položky nastavuje continue=0. Tudíž by se cyklus už dál neměl provádět. Funkce vrací 0, takže podmínka OR vyhodnocuje další podmínku a ta je 0
Pozn:
Právě že v té funkci jsem si to zkontroloval, že vrací skutečně 0. Dal jsem tam echo "Nejaky text" a tak jsem to vizualne zkontroloval že to funguje správně.
-
while funkcia; do ... done
Cyklus sa opakuje kym funkcia vracia hodnotu 0. Na skoncenie treba vrati 1,vid TLDP (http://tldp.org/LDP/abs/html/loops1.html)
-
while funkcia; do ... done
Cyklus sa opakuje kym funkcia vracia hodnotu 0. Na skoncenie treba vrati 1,vid TLDP (http://tldp.org/LDP/abs/html/loops1.html)
Aha, já myslel, že to je naopak!
-
Aha, já myslel, že to je naopak!
nenulova navratova hodnota znamena chybu
-
No skvělé. Končeně to funguje.
Dík za pomoc.