Podczas wyłuskiwania zmiennej bash
musisz użyć $
znaku. Niemniej jednak wydaje się, że następujące działa dobrze:
x=5
[[ x -gt 2 ]]
Czy ktoś może to wyjaśnić?
Edycja: (więcej informacji)
Chodzi mi o to, w jaki sposób i dlaczego polecenie [[]] usuwa dane z mojej zmiennej x bez znaku $. I tak, jeśli x = 1, instrukcja jest oceniana na false (zwracany status 1)
bash
bash-expansion
Gość
źródło
źródło
x=1
następnie[[ x -gt 2]]
?Odpowiedzi:
Powodem jest to, że
-eq
wymusza arytmetyczną ocenę argumentów.Operator arytmetyczna:
-eq
,-gt
,-lt
,-ge
,-le
i-ne
wewnątrz[[ ]]
(w KSH) i zsh, środki do automatycznego rozszerzania nazwy zmiennych jak w języku C, nie potrzeba czołowym$
.W celu potwierdzenia musimy zajrzeć do kodu źródłowego bash. Instrukcja nie oferuje bezpośredniego potwierdzenia.
Wewnątrz
test.c
przetwarzania operatorów arytmetycznych można znaleźć tę funkcję:Gdzie
s
it
są oba operandy. Operandy są przekazywane do tej funkcji:Funkcja
evalexp
jest zdefiniowana wewnątrzexpr.c
, która ma następujący nagłówek:Tak więc, obie strony operatora arytmetycznego popadają (bezpośrednio) w ocenę wyrażeń arytmetycznych. Bezpośrednio, nie ma ale, nie ma.
W praktyce z:
Oba te niepowodzenia:
Co jest poprawne,
x
nie jest rozwijane ix
nie jest równe liczbie.Jednak:
Zmienna o nazwie
x
zostaje rozwinięta (nawet bez $).Nie dzieje się tak
[…]
w przypadku zsh ani bash (dzieje się to w ksh).To samo co dzieje się w
$((…))
:I proszę zrozumieć, że jest to (bardzo) rekurencyjne (z wyjątkiem myślnika i yash):
A 😮
I dość ryzykowne:
Błąd składniowy można łatwo uniknąć:
Jak mówi przysłowie: odkaż swój wkład
koniec 😮
Zarówno (starsze) zewnętrzne
/usr/bin/test
(nie wbudowanetest
), jak i jeszcze starsze, a także zewnętrzneexpr
nie rozwijają wyrażeń tylko liczb całkowitych (i najwyraźniej tylko liczb dziesiętnych):źródło
[[
słowo kluczowe operatory i operandy są wykrywane po odczytaniu polecenia, a nie po rozwinięciu. W ten sposób[[
można leczyć-eq
w bardziej inteligentny sposób niż, powiedzmy[
. Zastanawiam się jednak: gdzie możemy znaleźć dokumentację dotyczącą logiki używanej przez bash do interpretacji poleceń złożonych? Nie wydaje mi się to dość oczywiste i najwyraźniej nie jestem w stanie znaleźć satysfakcjonujących wyjaśnień wman
lubinfo bash
.test
części człowieka zshbuiltins operatorów arytmetycznych oczekiwać całkowitą argumentów zamiast wyrażeń arytmetycznych . Co potwierdza, że niektóre argumenty są traktowane jako wyrażenia arytmetyczne przez wbudowany test w warunkach nieokreślonych w tym cytacie. Potwierdzę kodem źródłowym….…Operandy porównań liczbowych
-eq
,-gt
,-lt
,-ge
,-le
i-ne
są traktowane jako wyrażeń arytmetycznych. Z pewnymi ograniczeniami nadal muszą być słowami pojedynczymi.Zachowanie nazw zmiennych w wyrażeniach arytmetycznych opisano w Shell Arithmetic :
i również:
Ale tak naprawdę nie mogę znaleźć części dokumentacji, w której jest powiedziane, że porównania numeryczne przyjmują wyrażenia arytmetyczne. Nie jest to opisane w Konstrukcjach warunkowych pod
[[
, ani nie jest opisane w Wyrażeniach warunkowych Bash .Ale eksperymentalnie wydaje się, że działa jak wspomniano powyżej.
Więc takie rzeczy działają:
to też (wartość zmiennej jest oceniana):
Ale tak nie jest; nie jest to pojedyncze słowo powłoki podczas
[[ .. ]]
analizowania, więc występuje błąd składniowy w warunkowym:W innych kontekstach arytmetycznych wyrażenie nie musi być spacją. Wypisuje się
999
, gdy nawiasy jednoznacznie ograniczają wyrażenie arytmetyczne w indeksie:Z drugiej strony
=
porównanie jest dopasowaniem wzorca i nie obejmuje arytmetyki, ani automatycznego rozszerzania zmiennych wykonywanego w kontekście arytmetycznym (konstrukcje warunkowe):Jest to więc fałsz, ponieważ ciągi znaków są oczywiście różne:
jak to jest, mimo że wartości liczbowe są takie same:
i tutaj również porównywane są ciągi (
x
i6
), są one różne:Spowoduje to jednak rozwinięcie zmiennej, więc jest to prawdą:
źródło
arg1 OP arg2
mówi, że argumenty mogą być dodatnimi lub ujemnymi liczbami całkowitymi, co, jak sądzę, powinno sugerować, że są one traktowane jako wyrażenia arytmetyczne. Myląco oznacza to również, że nie mogą być zerowe. :)[
i nie są to wyrażenia arytmetyczne. Zamiast tego Bash narzeka na wartości całkowite.[
jest poleceniem zewnętrznym, nie ma dostępu do zmiennych powłoki. Często jest zoptymalizowany za pomocą wbudowanego polecenia, ale nadal zachowuje się tak samo.[
również[[
. Nawet z[
operandami-eq
i przyjaciółmi są / muszą być liczbami całkowitymi, więc ten opis również ma zastosowanie. Przyjmowanie „musi być liczbami całkowitymi”, co oznacza „są interpretowane jako wyrażenia arytmetyczne”, nie ma zastosowania w obu przypadkach. (Prawdopodobnie przynajmniej częściowo z powodu[
działania jak zwykłe polecenie, jak mówisz.)Tak, twoja obserwacja jest prawidłowa, interpretacja zmiennych odbywa się na wyrażeniach w podwójnych nawiasach
[[ ]]
, więc nie musisz umieszczać$
przed nazwą zmiennej.Jest to wyraźnie określone w
bash
instrukcji:Zauważ, że nie dotyczy to wersji z pojedynczym nawiasiem
[ ]
, ponieważ[
nie jest słowem kluczowym powłoki (składnią), ale raczej poleceniem (w bash jest wbudowane, inne powłoki mogą używać zewnętrznego, liniowanego do testowania).źródło
(x=1; [[ $x = 1 ]]; echo $?)
zwraca0
,(x=1; [[ x = 1 ]]; echo $?)
zwraca1
, tzn. Niex
porównuje się interpretacji parametrów podczas porównywania ciągów. To zachowanie wygląda jak ocena arytmetyczna wywołana rozszerzeniem arytmetycznym, czyli tym, co się dzieje(x=1; echo $((x+1)))
. (O ocenie arytmetycznejman bash
stwierdza: „W wyrażeniu do zmiennych powłoki można również odwoływać się według nazwy bez użycia składni interpretacji parametrów).-gt
operator oczekuje liczby, więc całe wyrażenie jest ponownie oceniane tak, jakby było w środku(())
, z drugiej strony==
oczekuje łańcuchów, więc zamiast tego uruchamiana jest funkcja dopasowania wzorca. Nie zagłębiałem się w kod źródłowy, ale brzmi rozsądnie.[
jest powłoką wbudowaną w bash.