Mam problem z jednym ze skryptów powłoki. Zapytałem kilku kolegów, ale wszyscy tylko potrząsali głowami (po pewnym zadrapaniu), więc przyszedłem tutaj po odpowiedź.
Według mojego zrozumienia następujący skrypt powłoki powinien wypisać „Count is 5” jako ostatni wiersz. Tyle że nie. Wyświetla „Liczba to 0”. Jeśli „podczas odczytu” zostanie zastąpione jakąkolwiek inną pętlą, działa dobrze. Oto skrypt:
echo „1”> input.data echo „2” >> input.data echo „3” >> input.data echo „4” >> input.data echo „5” >> input.data CNT = 0 dane wejściowe kota podczas czytania; robić niech CNT ++; echo „Zliczanie do $ CNT” gotowy echo „Liczba to $ CNT”
Dlaczego tak się dzieje i jak mogę temu zapobiec? Próbowałem tego w Debian Lenny i Squeeze, ten sam wynik (tj. Bash 3.2.39 i bash 4.1.5. W pełni przyznaję, że nie jestem kreatorem skryptów powłoki, więc wszelkie wskazówki będą mile widziane.
To rodzaj „powszechnego” błędu. Rury tworzą SubShells, więc
while read
działa na innej powłoce niż skrypt, co sprawia, że twojaCNT
zmienna nigdy się nie zmienia (tylko ta wewnątrz podpowłoki rury).echo
Zgrupuj ostatni z podpowłoką,while
aby to naprawić (istnieje wiele innych sposobów, aby to naprawić, to jest jeden. Odpowiedzi Iaina i Ignacio mają inne.)Długie wyjaśnienie:
CNT
skrypcie deklarujesz wartość 0;|
celuwhile read
;$CNT
zmienna jest eksportowana do SubShell o wartości 0;CNT
wartość do 5;echo
oryginalnaCNT
wartość 0.źródło
To działa
źródło
let CNT++
która powinna zamiastCNT="$((CNT+1))"
tego korzystać z rozszerzania arytmetycznego zgodnego z POSIX . Reszta jest już przenośna.Zamiast tego spróbuj przekazać dane do podpowłoki, tak jak plik przed pętlą while. Jest to podobne do rozwiązania Laina, ale zakłada, że nie chcesz jakiegoś pliku przerywanego:
źródło