Edycja: jest to bardziej kompletna wersja, która pokazuje więcej różnic między [
(aka test
) a [[
.
Poniższa tabela pokazuje, że niezależnie od tego, czy zmienna jest cytowana, czy nie, czy używasz nawiasów pojedynczych czy podwójnych i czy zmienna zawiera tylko spację, wpływają na to, czy test z lub bez -n/-z
jest odpowiedni do sprawdzania zmiennej.
| 1a 2a 3a 4a 5a 6a | 1b 2b 3b 4b 5b 6b
| [ [" [-n [-n" [-z [-z" | [[ [[" [[-n [[-n" [[-z [[-z"
-----+------------------------------------+------------------------------------
unset| false false true false true true | false false false false true true
null | false false true false true true | false false false false true true
space| false true true true true false| true true true true false false
zero | true true true true false false| true true true true false false
digit| true true true true false false| true true true true false false
char | true true true true false false| true true true true false false
hyphn| true true true true false false| true true true true false false
two | -err- true -err- true -err- false| true true true true false false
part | -err- true -err- true -err- false| true true true true false false
Tstr | true true -err- true -err- false| true true true true false false
Fsym | false true -err- true -err- false| true true true true false false
T= | true true -err- true -err- false| true true true true false false
F= | false true -err- true -err- false| true true true true false false
T!= | true true -err- true -err- false| true true true true false false
F!= | false true -err- true -err- false| true true true true false false
Teq | true true -err- true -err- false| true true true true false false
Feq | false true -err- true -err- false| true true true true false false
Tne | true true -err- true -err- false| true true true true false false
Fne | false true -err- true -err- false| true true true true false false
Jeśli chcesz wiedzieć, czy zmienna ma niezerową długość, wykonaj dowolną z następujących czynności:
- podaj zmienną w pojedynczych nawiasach (kolumna 2a)
- użyj
-n
i cytuj zmienną w pojedynczych nawiasach (kolumna 4a)
- używaj nawiasów podwójnych z cytowaniem lub bez i z lub bez
-n
(kolumny 1b - 4b)
Zauważ w kolumnie 1a rozpoczynającej się od wiersza oznaczonego „dwa”, że wynik wskazuje, że [
ocenia zawartość zmiennej tak, jakby były częścią wyrażenia warunkowego (wynik odpowiada twierdzeniu sugerowanemu przez „T” lub „F” w kolumna opisu). Gdy [[
jest używany (kolumna 1b), zawartość zmiennej jest postrzegana jako ciąg i nie jest analizowana.
Błędy w kolumnach 3a i 5a są spowodowane faktem, że wartość zmiennej zawiera spację, a zmienna nie jest cytowana. Ponownie, jak pokazano w kolumnach 3b i 5b, [[
ocenia zawartość zmiennej jako ciąg.
Odpowiednio, w przypadku testów ciągów o zerowej długości kolumny 6a, 5b i 6b pokazują prawidłowe sposoby wykonania tego. Zauważ również, że którykolwiek z tych testów może być zanegowany, jeśli negowanie wykazuje wyraźniejsze zamiary niż użycie odwrotnej operacji. Na przykład: if ! [[ -n $var ]]
.
Jeśli używasz [
, kluczem do upewnienia się, że nie otrzymasz nieoczekiwanych wyników, jest cytowanie zmiennej. Używanie [[
nie ma znaczenia.
Komunikaty o błędach, które są tłumione, to „oczekiwany operator jednoargumentowy” lub „oczekiwany operator binarny”.
To jest skrypt, który utworzył powyższą tabelę.
#!/bin/bash
# by Dennis Williamson
# 2010-10-06, revised 2010-11-10
# for http://stackoverflow.com/q/3869072
# designed to fit an 80 character terminal
dw=5 # description column width
w=6 # table column width
t () { printf '%-*s' "$w" " true"; }
f () { [[ $? == 1 ]] && printf '%-*s' "$w" " false" || printf '%-*s' "$w" " -err-"; }
o=/dev/null
echo ' | 1a 2a 3a 4a 5a 6a | 1b 2b 3b 4b 5b 6b'
echo ' | [ [" [-n [-n" [-z [-z" | [[ [[" [[-n [[-n" [[-z [[-z"'
echo '-----+------------------------------------+------------------------------------'
while read -r d t
do
printf '%-*s|' "$dw" "$d"
case $d in
unset) unset t ;;
space) t=' ' ;;
esac
[ $t ] 2>$o && t || f
[ "$t" ] && t || f
[ -n $t ] 2>$o && t || f
[ -n "$t" ] && t || f
[ -z $t ] 2>$o && t || f
[ -z "$t" ] && t || f
echo -n "|"
[[ $t ]] && t || f
[[ "$t" ]] && t || f
[[ -n $t ]] && t || f
[[ -n "$t" ]] && t || f
[[ -z $t ]] && t || f
[[ -z "$t" ]] && t || f
echo
done <<'EOF'
unset
null
space
zero 0
digit 1
char c
hyphn -z
two a b
part a -a
Tstr -n a
Fsym -h .
T= 1 = 1
F= 1 = 2
T!= 1 != 2
F!= 1 != 1
Teq 1 -eq 1
Feq 1 -eq 2
Tne 1 -ne 2
Fne 1 -ne 1
EOF
["
vs[-n"
(pierwsze pytanie PO) pokazuje, że są one całkowicie równoważne, prawda?[["
Lepiej jest użyć mocniejszego,
[[
jeśli chodzi o Bash.Zwykłe przypadki
Powyższe dwie konstrukcje wyglądają na czyste i czytelne. W większości przypadków powinny wystarczyć.
Zauważ, że nie musimy cytować wewnętrznych rozszerzeń,
[[
ponieważ nie ma niebezpieczeństwa dzielenia i globowania słów .Aby zapobiec delikatnym skargom Shellcheck na
[[ $var ]]
i[[ ! $var ]]
, moglibyśmy skorzystać z tej-n
opcji.Rzadkie przypadki
W rzadkim przypadku, gdy musimy wprowadzić rozróżnienie między „ustawieniem pustego ciągu” a „nie ustawieniem wcale”, moglibyśmy użyć tych:
Możemy również skorzystać z
-v
testu:Powiązane posty i dokumentacja
Istnieje wiele postów związanych z tym tematem. Tu jest kilka:
[[
vs[
[
vs[[
źródło
Oto kilka innych testów
Prawda, jeśli ciąg znaków nie jest pusty:
Prawda, jeśli ciąg znaków jest pusty:
źródło
Prawidłowa odpowiedź to:
Zwróć uwagę na użycie
[[...]]
, które poprawnie obsługuje cytowanie zmiennych za Ciebie.źródło
-n
gdy nie jest tak naprawdę potrzebne w Bash?Alternatywnym i być może bardziej przejrzystym sposobem oceny pustej zmiennej środowiskowej jest użycie ...
źródło
bash
jest ostrzejszym narzędziem niż jego poprzednicy.[ "$ENV_VARIABLE" != "" ]
będzie działał na każdej powłoce ztest
implementacją zgodną z POSIX - nie tylko bash, ale ash / dash / ksh / etc.-a
ani-o
nie łącz testów, zamiast tego używaj[ ... ] && [ ... ]
lub[ ... ] || [ ... ]
jedyne przypadki narożne, które mogą mieć zastosowanie do używania danych dowolnych zmiennych w teście, są jednoznacznie zamknięte.Użyj
case/esac
do przetestowania:źródło
case
jest przeznaczone.case
działa najlepiej, gdy istnieją więcej niż dwie alternatywy.case
nie jest przeznaczony do tego rodzaju zastosowań.