Prosíme přihlašte se nebo zaregistrujte.

Přihlašte se svým uživatelským jménem a heslem.
Vaše pomoc je stále potřeba!

Autor Téma: ret value  (Přečteno 1950 krát)

alfonz19

  • Aktivní člen
  • *
  • Příspěvků: 219
ret value
« kdy: 17 Dubna 2009, 20:24:33 »
Zdar,

mám napsanej skript, poslední co zbývá, je vrátit korektní návratovou hodnotu. Netušil jsem jakej to bude problém.

Takže o tom, co mám vrátit se dozvím někde v cyklu, resp. v ifu, který je zanořen ve whilu. Zkoušel jsem uvnitř cyklu volat exit 1 (ale to mi celý skript neukončí), zkoušel jsem nastavit hodnotu proměnné, kterou bych mimo cyklus přečetl s její hodnotou volal exit (ale hodnota nastavená v proměnné uvnitř cyklu se nepřenese mimo cyklus navzdory tomu že tato je deklarována vně cyklu), zkoušel jsem volat uvnitř cyklu exit 1 a mimo cyklus číst $? jestli tam snad nenajdu tu jedničku (ne). Tak a to je asi tak vše co mne napadá.

Takže jak se tato trivialita řeší v bashi???

arrange

  • Závislák
  • ***
  • Příspěvků: 4031
  • "jdu s hlavou vztyčenou..."
Re: ret value
« Odpověď #1 kdy: 17 Dubna 2009, 21:35:06 »
Asi jsem to nepochopil
Kód: [Vybrat]
$ echo "i=0; until [[ i -eq 20 ]]; do let i++; if [[ i -eq 15 ]]; then exit 1; fi; done; echo 'konec'" > /tmp/a
$ /tmp/a
$ echo $?
1
Vložil jsem do cyklu podmínku if a pak exitoval s jedničkou - slovo 'konec' se neobjevilo, protože skript nedojel do konce. Ve výstupu hlásí $? = 1

http://www.openstreetmap.org - mapy celého světa "wiki style"

alfonz19

  • Aktivní člen
  • *
  • Příspěvků: 219
Re: ret value
« Odpověď #2 kdy: 18 Dubna 2009, 11:20:30 »
o to horší to je, že tobě to funguje. Bash zatím docela boří moje znalosti a zvyky programování, což mi nedělá dobře.
Takže pošlu příklad skript, je delší, ale důležitých je jen pár posledních řádků kolem ifu. Asi nebude napsán optimálně, ale žádný div. V bashi jsem toho moc nenaprogramoval.

Kód: [Vybrat]
#!/bin/bash

function printUsageAndExit {
echo "Usage: checkFileForWrongIndentation.sh [-v] FILE";
echo;
echo "when swith -v is used then all lines with error is reported, otherwise only report that supplied file is not correct is reported."

                exit 1;
}

function testFileExistency {
if [ ! -e "$1" ]; then
printUsageAndExit;
fi
}
 
LINE_NUMBER=0;

if [ $# -eq 0 -o $# -gt 2 ]; then
printUsageAndExit;
fi

if [ $# -eq 1 ]; then
testFileExistency "$1"
FILE="$1";
VERBOSE=1;

else
#from here on we know, that two parameters were supplied, so we just check for -v switch presence

testFileExistency "$2"
FILE="$2";
if [ "$1" = "-v" ]; then
VERBOSE=0;
else
printUsageAndExit
fi
fi


cat "$FILE" | sed "s/^\([ \t]*\).*$/\"\1\"/" | sed "s/\t//g" | while read LINE; do
#echo "$LINE" | tr -d "\n" | wc -m | tr -d "\n"; echo ": \"$LINE\""

LINE_NUMBER=$(($LINE_NUMBER + 1));
SPACES=`echo -n "$LINE" | wc -m | tr "\n" " "`;
SPACES=$(($SPACES - 2));

if [ $SPACES -gt 3 ]; then
if [ $VERBOSE -eq 0 ]; then
echo "wrong indentation in file \"$FILE\" on line $LINE_NUMBER";
ERROR_FOUND=1;
else
echo "File $FILE has badly indented lines";
echo trying to quit;
exit 1;
echo failed;
#break;
fi
fi

done;
echo hmm

výstup:
File testingDir/SecurityUtil.java has badly indented lines
trying to quit
hmm

komentář: testingDir/SecurityUtil.java je soubor, který byl specifikován jako parametr. Je vidět, že exit skutečně něco udělal protože "failed" se nevypsalo, ale ZJEVNĚ nezpůsobil ukončení skriptu protože se vypíše "hmm" a protože se "hmm" vypíše korektně, pak je $? roven nule. Co je však zajímavější je to, že exit skutečně nastaví $? na 1, protože když výpis "hmm" zakomentuji, dostanu po provedení skritpu v $? jedničku. Proč tedy toto chování? Jaká je příčina, že tvůj exit ukončí skript a můj exist ne?

A jak je to s těmi proměnnými? Skutečně, když jsem v místě kde je teď exit (ten v cyklu) nastavil hodnotu nějaké proměnné, pak v místě výpisu "hmm" měla původní hodnotu - vypadá to, jako kdyby cyklus byl implemen uvnitř nějaké metody a veškeré parametry se mu předávají hodnotou (nemyslím paskalovskou "hodnotou", která je ve skutečnosti "hodnotou-výsledkem")

alfonz19

  • Aktivní člen
  • *
  • Příspěvků: 219
Re: ret value
« Odpověď #3 kdy: 18 Dubna 2009, 11:24:31 »
skript testuje, zdali není některý řádek ve zdrojácích odsazen 4 mezerami namísto jednoho tabulátoru, takže pokud bys to chtěl otestovat, tak příklad selhávajícího souboru je například:

Kód: [Vybrat]
this line is ok
    this line is not ok
  \t  this line is not ok either(substitute \t, I can't write tab symbol here.)

arrange

  • Závislák
  • ***
  • Příspěvků: 4031
  • "jdu s hlavou vztyčenou..."
Re: ret value
« Odpověď #4 kdy: 19 Dubna 2009, 19:00:18 »
Problém je v tom, že když "pipneš" výstup do while/until cyklu, spustí se child process s tímto cyklem, takže potom ten exit pouze ukončí ten child process, ne celý skript. Proto se tedy po done objeví ten nápis hmm.

Je to dokonce ještě horší: když si (při tomto způsobu použití) uprostřed toho cyklu nadefinuješ nějakou proměnnou, bash ji po výstupu z něho "zapomene".

V tomto případě by ale mělo stačit po ukončení cyklu testovat $? na návratovou hodnotu, jestli je -eq 1.

Snad jsem to vysvětlil srozumitelně. Viz také třeba
http://www.linuxprogrammingblog.com/pipe-in-bash-can-be-a-trap
http://ubuntuforums.org/showthread.php?t=312017
http://www.openstreetmap.org - mapy celého světa "wiki style"

 

Provoz zaštiťuje spolek OpenAlt.