Moje pytanie dotyczy wartości zwracanych przez ten kod:
if [ -n ]; then echo "true"; else echo "false"; fi
To drukuje true
.
Jego uzupełniający test wykorzystujący [ -z ]
również odbitki true
:
if [ -z ]; then echo "true"; else echo "false"; fi
Dlaczego w powyższym kodzie [ -n ]
test zakłada, że wartość ciągu nie jest wcale przekazywana, ponieważ nie jest zerowa?
Poniższy kod zostanie wydrukowany false
. Jest to oczekiwane, ponieważ przekazana wartość ciągu jest zerowa i ma zerową długość.
if [ -n "" ]; then echo "true"; else echo "false"; fi
[ -t ]
testowałem, czy stdout był terminalem (skrót od[ -t 1 ]
), a niektóre powłoki wciąż to robią (w przypadku,ksh93
gdy-t
jest to dosłowne), więc lepiej jest użyć[ -n "$var" ]
niż[ "$var" ]
. Chociaż nadal nie udałoby się to w niektórych starychtest
implementacjach dla wartości$var
podobnych=
, w którym to przypadku[ "" != "$var" ]
lub[ "x$var" != x ]
lubcase $x in "")...
może być lepsza.-o
tutaj. W niektórych powłokach, takich jakbash
,-o
jest zarówno jednoargumentowy (sprawdź, czy ustawiono opcję), jak i binarny (lub), więc rzeczy takie[ ! -o monitor ]
są niejednoznaczne. Jest to badanie, żemonitor
opcja ta nie jest ustawiona, albo, że albo!
czymonitor
są niepuste ciągi? Decydują reguły POSIX: te ostatnie (z czym to się różni[[ ! -o monitor ]]
).[ -n ]
nie korzysta z-n
testu.-n
W[ -n ]
nie jest test w ogóle. Gdy między[
i jest tylko jeden argument]
, argument ten jest testowanym ciągiem, aby sprawdzić, czy jest pusty. Nawet jeśli ten ciąg ma wiodące-
, nadal jest interpretowany jako operand, a nie test. Ponieważ łańcuch-n
nie jest pusty - zawiera dwa znaki,-
in
, nie zerowy characters--[ -n ]
wartość true.Jak mówi Ignacio Vazquez-Abrams , gdzie
string
jest pojedynczy argument, test przeprowadzony nastring
in jest taki sam jak test przeprowadzony na nim . Kiedy tak się dzieje , nic specjalnego się nie dzieje. W a drugi w to po prostu ciągi testowane na pustkę.[ string ]
[ -n string ]
string
-n
-n
[ -n ]
-n
[ -n -n ]
Gdy pomiędzy
[
i jest tylko jeden argument]
, argument ten jest zawsze ciągiem do przetestowania pod kątem niełaskawości, nawet jeśli przypadkiem nazywa się go tak samo jak test. Podobnie, gdy istnieją dwa argumenty pomiędzy[
i]
i pierwszy z nich jest-n
, drugi jest zawsze ciągiem do przetestowania pod kątem nieuprzejmości, nawet jeśli zdarza się, że nazywa się tak samo jak test. Jest tak po prostu dlatego, że składnia for[
nalega, aby pojedynczy argument pomiędzy[
i]
po-n
był operandem łańcuchowym.Z tego samego powodu,
[ -n ]
który nie korzysta z-n
testu,[ -z ]
nie korzysta z-z
testu.Możesz dowiedzieć się więcej na temat
[
wbash
badając pomoc dla niego. Zauważ, że jest to wbudowana powłoka :Możesz więc uruchomić,
help [
aby uzyskać pomoc:Aby uzyskać więcej informacji, w tym o tym, jakie testy są obsługiwane i jak one działają, będziesz musiał zobaczyć pomoc na temat
test
. Po uruchomieniu poleceniahelp test
otrzymasz szczegółową listę. Zamiast reprodukować wszystko, oto część o operatorach łańcuchów:Zauważ to
-n STRING
i po prostuSTRING
zrób to samo: sprawdzają, czy łańcuchSTRING
nie jest pusty.źródło
IFS
białe znaki; zmienne zawierające wiele słów zamiast zera dają inny efekt i mogą spowodować uruchomienie zupełnie innego testu. Ciągi, które pojawiają się dosłownie z zamiarem bycia operandami, będą działać poprawnie tylko wtedy, gdy nie będą zawierały spacji ani tabulatorów, lub jeśli będą cytowane. Odpowiedź stałaby się znacznie dłuższa i bardziej skomplikowana, gdybym omawiał ten temat w przystępny sposób. Jeśli zdecydujesz się opublikować odpowiedź, nie krępuj się tutaj @ mnie![ "$var" ]
nigdy nie byłby użyteczny jako test, ponieważ$var
mógłby się rozwinąć-n
.[ -n ]
jest prawdą, ponieważ[
polecenie (inaczejtest
polecenie) działa na podstawie podanej liczby argumentów. Jeśli podano tylko jeden argument, wynikiem jest „prawda”, jeśli argument jest niepustym łańcuchem. „-n” jest łańcuchem zawierającym 2 znaki, niepustym, dlatego „prawda”.źródło