Odpowiedzi:
W Basha, test
i [
są powłoki builtins.
Podwójny uchwyt , który jest powłoką Hasło umożliwia dodatkową funkcjonalność. Na przykład, można użyć &&
i ||
zamiast -a
a -o
i tam regularne operator dopasowanie wyraz =~
.
Ponadto w prostym teście nawiasy kwadratowe wydają się oceniać znacznie szybciej niż pojedyncze.
$ time for ((i=0; i<10000000; i++)); do [[ "$i" = 1000 ]]; done
real 0m24.548s
user 0m24.337s
sys 0m0.036s
$ time for ((i=0; i<10000000; i++)); do [ "$i" = 1000 ]; done
real 0m33.478s
user 0m33.478s
sys 0m0.000s
Nawiasy klamrowe oprócz ograniczania nazwy zmiennej służą do rozszerzania parametrów, dzięki czemu można wykonywać następujące czynności:
Obetnij zawartość zmiennej
$ var="abcde"; echo ${var%d*}
abc
Dokonaj podstawień podobnych do sed
$ var="abcde"; echo ${var/de/12}
abc12
Użyj wartości domyślnej
$ default="hello"; unset var; echo ${var:-$default}
hello
i kilka innych
Ponadto rozszerzenia nawiasów tworzą listy ciągów, które są zazwyczaj iterowane w pętlach:
$ echo f{oo,ee,a}d
food feed fad
$ mv error.log{,.OLD}
(error.log is renamed to error.log.OLD because the brace expression
expands to "mv error.log error.log.OLD")
$ for num in {000..2}; do echo "$num"; done
000
001
002
$ echo {00..8..2}
00 02 04 06 08
$ echo {D..T..4}
D H L P T
Pamiętaj, że wiodące funkcje zerowania i przyrostu nie były dostępne przed Bash 4.
Dzięki gboffi za przypomnienie mi o rozszerzeniach aparatu.
Podwójne nawiasy są używane do operacji arytmetycznych :
((a++))
((meaning = 42))
for ((i=0; i<10; i++))
echo $((a + b + (14 * c)))
i pozwalają ominąć znaki dolara na zmiennych całkowitych i tablicowych oraz zawierać spacje wokół operatorów dla czytelności.
Pojedyncze nawiasy klamrowe są również używane dla indeksów tablicowych :
array[4]="hello"
element=${array[index]}
Nawiasy klamrowe są wymagane dla (większości / wszystkich?) Odniesień do tablicy po prawej stronie.
Komentarz ephemienta przypomniał mi, że nawiasy są również używane do podpowłoki. I że są one używane do tworzenia tablic.
array=(1 2 3)
echo ${array[1]}
2
:
.
$[expression]
:; to jest stara, przestarzała składnia arytmetyczna wyrażenia dla nowszej, preferowanej składni:$((expression))
bash
jest tworzenie sekwencji, jak wspomniano poniżej peryferyjnie ( stackoverflow.com/a/8552128/2749397 ) Chciałbym skomentować nieco tę funkcję (o której nie wspomniałeś ;-) m pozwalając sobie na użycie najczęściej głosowanej odpowiedzi jako pojazdu ... Dwa przykłady literałów sekwencji: echo {01..12}
-> 01 02 03 04 05 06 07 08 09 10 11 12
(zwróć uwagę na początkowe zero); echo {C..Q}
-> C D E F G H I J K L M N O P Q
. Jego głównym zastosowaniem są pętle, np. for cnt in {01..12} ; do ... ${cnt} ... ; done
echo {01..12..2}
-> „01 03 05 07 09 11”. Dzięki za przypomnienie o sekwencjach. Dodam to do mojej odpowiedzi.
Pojedynczy nawias kwadratowy ( [
) zwykle wywołuje program o nazwie [
; man test
lub man [
po więcej informacji. Przykład:
$ VARIABLE=abcdef
$ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi
yes
Podwójny nawias ( [[
) robi to samo (w zasadzie) jak pojedynczy nawias, ale jest wbudowany w bash.
$ VARIABLE=abcdef
$ if [[ $VARIABLE == 123456 ]] ; then echo yes ; else echo no ; fi
no
Nawiasy ( ()
) służą do tworzenia podpowłoki. Na przykład:
$ pwd
/home/user
$ (cd /tmp; pwd)
/tmp
$ pwd
/home/user
Jak widać, podpowłoka umożliwia wykonywanie operacji bez wpływu na środowisko bieżącej powłoki.
(a) Aparat ortodontyczny ({}
) służą do jednoznacznej identyfikacji zmiennych. Przykład:
$ VARIABLE=abcdef
$ echo Variable: $VARIABLE
Variable: abcdef
$ echo Variable: $VARIABLE123456
Variable:
$ echo Variable: ${VARIABLE}123456
Variable: abcdef123456
(b) Nawiasy klamrowe są również używane do wykonywania sekwencji poleceń w bieżącym kontekście powłoki, np
$ { date; top -b -n1 | head ; } >logfile
# 'date' and 'top' output are concatenated,
# could be useful sometimes to hunt for a top loader )
$ { date; make 2>&1; date; } | tee logfile
# now we can calculate the duration of a build from the logfile
Istnieje jednak subtelna różnica składniowa z ( )
(patrz odniesienie do bash ); zasadniczo, średnik ;
po ostatnim poleceniu w szelki jest koniecznością, a szelki {
, }
muszą być otoczone spacjami.
[
tak naprawdę jest wbudowany w Bash, ale powinien działać jak /bin/[
w przeciwieństwie do [[
wbudowanego. [[
ma różne funkcje, takie jak bardziej logiczne operacje i różne role cytowania. Dodatkowo: pojedyncze nawiasy są również używane do tablic, podstawiania procesów i rozszerzonych globów; w arytmetyce stosowane są podwójne nawiasy; nawiasy klamrowe {}
są używane do grupowania poleceń lub mnóstwa typów interpretacji parametrów, interpretacji nawiasów lub interpretacji sekwencji. Jestem pewien, że przegapiłem też inne zastosowania ...
if [ $VARIABLE == abcdef ]
to bazizm, którego - choć działa - prawdopodobnie należy go unikać; jawnie użyj bash ( if [[ ...==...]]
) lub wyjaśnij, że używasz bardziej tradycyjnej metody warunkowej ( if [ "$VARIABLE" = "abcdef" ]
). Prawdopodobnie skrypty powinny zaczynać się tak prosto i przenośnie, jak to możliwe, dopóki nie będą naprawdę potrzebować funkcji specyficznych dla bash (z tego czy innego powodu). Ale w każdym razie intencja powinna być jasna; „=” i „==” oraz „[[” i „[” działają inaczej, a ich użycie powinno być spójne.
[ "$var" = ".."]
zamiast ==
, podczas gdy w C przypisuje zamiast testowania (i jest dość częstą przyczyną błędów) ... dlaczego nie „t test
używać ==
zamiast =
? ktokolwiek wie?
/usr/bin/[
nie jest dowiązaniem symbolicznym do /usr/bin/test
, a nawet więcej: te programy mają nawet kilka różnych rozmiarów!
)
jest częścią case
składni instrukcji kończącej wiersz wielkości liter. Nie ma nawiasu otwierającego. To mnie odrzuciło, gdy zobaczyłem to po raz pierwszy.
Wsporniki
if [ CONDITION ] Test construct
if [[ CONDITION ]] Extended test construct
Array[1]=element1 Array initialization
[a-z] Range of characters within a Regular Expression
$[ expression ] A non-standard & obsolete version of $(( expression )) [1]
[1] http://wiki.bash-hackers.org/scripting/obsolete
Nawiasy klamrowe
${variable} Parameter substitution
${!variable} Indirect variable reference
{ command1; command2; . . . commandN; } Block of code
{string1,string2,string3,...} Brace expansion
{a..z} Extended brace expansion
{} Text replacement, after find and xargs
Zdanie wtrącone
( command1; command2 ) Command group executed within a subshell
Array=(element1 element2 element3) Array initialization
result=$(COMMAND) Command substitution, new style
>(COMMAND) Process substitution
<(COMMAND) Process substitution
Podwójne nawiasy
(( var = 78 )) Integer arithmetic
var=$(( 20 + 5 )) Integer arithmetic, with variable assignment
(( var++ )) C-style variable increment
(( var-- )) C-style variable decrement
(( var0 = var1<98?9:21 )) C-style ternary operation
$(varname)
nie ma związku ze składnią bash. Jest to część składni Makefile .
$(varname)
nie ma związku ze składnią bash w twoim przypadku.
Chciałem tylko dodać te z TLDP :
~:$ echo $SHELL
/bin/bash
~:$ echo ${#SHELL}
9
~:$ ARRAY=(one two three)
~:$ echo ${#ARRAY}
3
~:$ echo ${TEST:-test}
test
~:$ echo $TEST
~:$ export TEST=a_string
~:$ echo ${TEST:-test}
a_string
~:$ echo ${TEST2:-$TEST}
a_string
~:$ echo $TEST2
~:$ echo ${TEST2:=$TEST}
a_string
~:$ echo $TEST2
a_string
~:$ export STRING="thisisaverylongname"
~:$ echo ${STRING:4}
isaverylongname
~:$ echo ${STRING:6:5}
avery
~:$ echo ${ARRAY[*]}
one two one three one four
~:$ echo ${ARRAY[*]#one}
two three four
~:$ echo ${ARRAY[*]#t}
one wo one hree one four
~:$ echo ${ARRAY[*]#t*}
one wo one hree one four
~:$ echo ${ARRAY[*]##t*}
one one one four
~:$ echo $STRING
thisisaverylongname
~:$ echo ${STRING%name}
thisisaverylong
~:$ echo ${STRING/name/string}
thisisaverylongstring
echo ${#ARRAY}
wyświetla trzy, ponieważ pierwszy element ARRAY
zawiera trzy znaki, a nie dlatego, że zawiera trzy elementy! Aby wydrukować liczbę elementów, użyj echo ${#ARRAY[@]}
.
${TEST:-test}
jest równe, $TEST
jeśli zmienna TEST
istnieje, w przeciwnym razie po prostu zwraca ciąg „test”. Jest jeszcze inna wersja, która robi jeszcze więcej: ${TEST:=test}
--- która równa się również, $TEST
jeśli TEST istnieje, ale ilekroć nie istnieje, tworzy zmienną TEST
i przypisuje wartość „test”, a także staje się wartością całego wyrażenia.
Różnica między testem , [ i [[ jest szczegółowo wyjaśniona w BashFAQ .
Krótko mówiąc: test implementuje starą, przenośną składnię polecenia. W prawie wszystkich powłokach (najstarsze powłoki Bourne'a są wyjątkiem), [jest synonimem testu (ale wymaga ostatniego argumentu]). Chociaż wszystkie współczesne powłoki mają wbudowane implementacje [, zwykle nadal istnieje zewnętrzny plik wykonywalny o tej nazwie, np. / Bin / [.
[[to nowa ulepszona wersja, która jest słowem kluczowym, a nie programem. Ma to korzystny wpływ na łatwość użycia, jak pokazano poniżej. [[jest rozumiany przez KornShell i BASH (np. 2.03), ale nie przez starsze POSIX lub BourneShell.
I wniosek:
Kiedy należy użyć nowego polecenia testowego [[, a kiedy starego [? Jeśli problemem jest przenośność do BourneShell, należy użyć starej składni. Jeśli z drugiej strony skrypt wymaga BASH lub KornShell, nowa składnia jest znacznie bardziej elastyczna.
()
W definicji funkcji używane są
nawiasy :
function_name () { command1 ; command2 ; }
Oto powód, dla którego musisz uciec od nawiasów nawet w parametrach polecenia:
$ echo (
bash: syntax error near unexpected token `newline'
$ echo \(
(
$ echo () { command echo The command echo was redefined. ; }
$ echo anything
The command echo was redefined.
unset -f echo
. Zobaczyć help unset
.
Truncate the contents of a variable
$ var="abcde"; echo ${var%d*}
abc
Make substitutions similar to sed
$ var="abcde"; echo ${var/de/12}
abc12
Use a default value
$ default="hello"; unset var; echo ${var:-$default}
hello