Cudzysłowy uniemożliwiają „dzielenie słów”. To znaczy: dzielenie zmiennych na wiele elementów przy znakach spacji (a ściślej, w odstępach, tabulatorach i znakach nowej linii, jak określono w wartości domyślnej $IFSzmiennej powłoki).
Na przykład,
$ var="one two"
$ howmany(){ echo $#; }
$ howmany $var
2
$ howmany "$var"
1
Tutaj definiujemy howmanyfunkcję, która po prostu informuje nas o liczbie podanych parametrów pozycyjnych. Jak widać, do zmiennej przekazywane są dwa elementy, a wraz z cudzysłowami tekst w zmiennej jest traktowany jako jedna jednostka.
Jest to ważne dla dokładnego przekazywania informacji. Na przykład, jeśli zmienna zawiera ścieżkę do pliku, a nazwa pliku zawiera spacje w dowolnym miejscu na ścieżce, polecenie, które próbujesz uruchomić, może zakończyć się niepowodzeniem lub dać niedokładne wyniki. Gdybyśmy próbowali utworzyć plik ze $varzmienną, touch $varutworzylibyśmy dwa pliki, ale touch "$var"tylko jeden.
To samo dotyczy twojej [ "$currentoutput" != "$lastoutput" ]części. Ten konkretny test przeprowadza porównanie dwóch ciągów. Po uruchomieniu testu [polecenie musi zobaczyć 3 argumenty - ciąg tekstowy, !=operator i kolejny ciąg tekstowy. Trzymanie podwójnych cudzysłowów zapobiega dzieleniu słów, a [polecenie rozpoznaje dokładnie 3 argumenty. Co się stanie, jeśli zmienne nie będą cytowane?
$ var="hello world"
$ foo="hi world"
$ [ $var != $foo ]
bash: [: too many arguments
$
Tutaj występuje dzielenie słów, a zamiast tego [widzimy dwa ciągi, helloa worldnastępnie !=, a następnie dwa inne ciągi hi world. Kluczową kwestią jest to, że bez podwójnych cudzysłowów zawartość zmiennych należy rozumieć jako oddzielne jednostki, a nie jedną całość.
Przypisanie podstawienia polecenia nie wymaga podwójnych cudzysłowów jak w
var=$( df )
gdzie dfzapisano dane wyjściowe polecenia var. Jednak dobrym zwyczajem jest zawsze podwójne cytowanie zmiennych i zastępowanie poleceń, $(...)chyba że faktycznie chcesz, aby dane wyjściowe były traktowane jako osobne elementy.
Na marginesie:
while [ true ]
część może być
while true
[to polecenie, które ocenia jego argumenty i [ whatever ]jest zawsze prawdziwe, niezależnie od tego, co jest w środku. Natomiast while trueużywa polecenia, truektóre zawsze zwraca status wyjścia pomyślnego zakończenia (i właśnie tego whilepotrzebuje pętla). Różnica polega na nieco większej przejrzystości i mniejszej liczbie przeprowadzonych testów. Możesz też użyć :zamiasttrue
Podwójne cytaty echo "" date and Timeczęściowo mogłyby zostać prawdopodobnie usunięte. Po prostu wstawiają pusty ciąg i dodają dodatkową przestrzeń do wyniku. Jeśli jest to pożądane, możesz je tam zachować, ale w tym przypadku nie ma żadnej szczególnej wartości funkcjonalnej.
lsusb >> test.log
Ta część prawdopodobnie mogłaby zostać zastąpiona echo "$currentoutput" >> test.log. Nie ma powodu, aby uruchomić lsusbponownie po tym, jak już został uruchomiony currentoutput=$(lsusb). W przypadkach, gdy końcowe znaki nowej linii
muszą zostać zachowane na wyjściu - można było zobaczyć wartość przy wielokrotnym uruchamianiu polecenia, ale w przypadku lsusbtakiej potrzeby nie jest to konieczne. Im mniej wywołujesz zewnętrznych poleceń, tym lepiej, ponieważ każde wywołanie niewbudowanego polecenia powoduje koszty procesora, zużycia pamięci i czasu wykonania (nawet jeśli polecenia są prawdopodobnie wstępnie ładowane z pamięci).
Zobacz też:
while [ true ]tworzy nieskończoną pętlę, ale być może nie z tego powodu, dla którego tak myślisz;while [ false ]również produkuje nieskończoną pętlę, bo z jednym argumentem,[ ... ]uda, jeśli ten argument jest niepusty ciąg.while truerzeczywiście uruchomić polecenie nazwietrue(które zawsze udaje).