Câu trả lời:
Trong Bash, test
và [
được xây dựng shell.
Dấu ngoặc kép , là một từ khóa shell, cho phép chức năng bổ sung. Ví dụ, bạn có thể sử dụng &&
và ||
thay vì -a
và -o
và có một nhà điều hành phù hợp với biểu thức chính quy =~
.
Ngoài ra, trong một thử nghiệm đơn giản, dấu ngoặc vuông đôi dường như đánh giá khá nhanh hơn nhiều so với dấu ngoặc đơn.
$ 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
Các dấu ngoặc nhọn, ngoài việc phân định một tên biến được sử dụng để mở rộng tham số để bạn có thể thực hiện những việc như:
Cắt bớt nội dung của một biến
$ var="abcde"; echo ${var%d*}
abc
Thay thế tương tự như sed
$ var="abcde"; echo ${var/de/12}
abc12
Sử dụng một giá trị mặc định
$ default="hello"; unset var; echo ${var:-$default}
hello
và nhiều hơn nữa
Ngoài ra, mở rộng dấu ngoặc tạo ra danh sách các chuỗi thường được lặp lại trong các vòng lặp:
$ 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
Lưu ý rằng các tính năng gia tăng và không hàng đầu không có sẵn trước Bash 4.
Cảm ơn gboffi đã nhắc nhở tôi về việc mở rộng niềng răng.
Dấu ngoặc kép được sử dụng cho các phép toán số học :
((a++))
((meaning = 42))
for ((i=0; i<10; i++))
echo $((a + b + (14 * c)))
và chúng cho phép bạn bỏ qua các ký hiệu đô la trên các biến số nguyên và mảng và bao gồm các khoảng trắng xung quanh các toán tử để dễ đọc.
Dấu ngoặc đơn cũng được sử dụng cho các chỉ số mảng :
array[4]="hello"
element=${array[index]}
Nẹp xoăn được yêu cầu cho các tham chiếu mảng (hầu hết / tất cả?) Ở phía bên tay phải.
Nhận xét của ephemient nhắc nhở tôi rằng dấu ngoặc đơn cũng được sử dụng cho subshells. Và chúng được sử dụng để tạo mảng.
array=(1 2 3)
echo ${array[1]}
2
:
.
$[expression]
; đây là cú pháp biểu thức số học cũ, không dùng nữa cho cú pháp ưa thích mới hơn:$((expression))
bash
là tạo các chuỗi, như được đề cập ngoại vi bên dưới ( stackoverflow.com/a/8552128/2749397 ) Như tôi muốn bình luận một chút về tính năng này (như bạn đã không đề cập đến nó ;-) I ' m lấy tự do sử dụng câu trả lời được bình chọn nhiều nhất làm phương tiện ... Hai ví dụ về chuỗi chữ: echo {01..12}
-> 01 02 03 04 05 06 07 08 09 10 11 12
(lưu ý số không ban đầu); echo {C..Q}
-> C D E F G H I J K L M N O P Q
. Công dụng chính của nó là trong các vòng lặp, ví dụ: for cnt in {01..12} ; do ... ${cnt} ... ; done
echo {01..12..2}
-> "01 03 05 07 09 11". Cảm ơn đã nhắc nhở về trình tự. Tôi sẽ thêm nó vào câu trả lời của tôi.
Một ngoặc đơn ( [
) thường thực sự gọi một chương trình có tên [
; man test
hoặc man [
để biết thêm. Thí dụ:
$ VARIABLE=abcdef
$ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi
yes
Dấu ngoặc kép ( [[
) thực hiện cùng một thứ (về cơ bản) như một dấu ngoặc đơn, nhưng là một giá trị dựng sẵn.
$ VARIABLE=abcdef
$ if [[ $VARIABLE == 123456 ]] ; then echo yes ; else echo no ; fi
no
Dấu ngoặc đơn ( ()
) được sử dụng để tạo một lớp con. Ví dụ:
$ pwd
/home/user
$ (cd /tmp; pwd)
/tmp
$ pwd
/home/user
Như bạn có thể thấy, lớp con cho phép bạn thực hiện các thao tác mà không ảnh hưởng đến môi trường của trình bao hiện tại.
(a) Niềng răng ( {}
) được sử dụng để xác định rõ ràng các biến. Thí dụ:
$ VARIABLE=abcdef
$ echo Variable: $VARIABLE
Variable: abcdef
$ echo Variable: $VARIABLE123456
Variable:
$ echo Variable: ${VARIABLE}123456
Variable: abcdef123456
(b) Niềng răng cũng được sử dụng để thực hiện một chuỗi các lệnh trong bối cảnh shell hiện tại , ví dụ
$ { 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
Có một sự khác biệt cú pháp tinh tế với ( )
, mặc dù (xem tài liệu tham khảo bash ); về cơ bản, dấu chấm phẩy ;
sau câu lệnh cuối cùng trong niềng răng là điều bắt buộc, và niềng răng {
, }
phải được bao quanh bởi không gian.
[
thực ra là một nội trang trong Bash, nhưng nó được cho là hoạt động như /bin/[
trái ngược với [[
nội dung. [[
có các tính năng khác nhau, như các hoạt động logic hơn và vai trò trích dẫn khác nhau. Ngoài ra: các dấu ngoặc đơn cũng được sử dụng cho các mảng, thay thế quá trình và các chuỗi mở rộng; dấu ngoặc kép được sử dụng cho số học; dấu ngoặc nhọn {}
được sử dụng để nhóm lệnh hoặc vô số kiểu mở rộng tham số hoặc mở rộng dấu ngoặc hoặc mở rộng chuỗi. Tôi chắc chắn tôi cũng đã bỏ lỡ một số cách sử dụng khác ...
if [ $VARIABLE == abcdef ]
là một bashism - mặc dù nó hoạt động - có lẽ nên tránh; hoặc sử dụng rõ ràng bash ( if [[ ...==...]]
) hoặc làm rõ rằng bạn đang sử dụng điều kiện truyền thống hơn ( if [ "$VARIABLE" = "abcdef" ]
). Có thể cho rằng, các tập lệnh nên bắt đầu đơn giản và dễ mang theo nhất có thể, cho đến khi chúng thực sự cần các tính năng dành riêng cho bash (vì lý do này hay lý do khác). Nhưng trong mọi trường hợp, ý định nên rõ ràng; "=" và "==" và "[[" và "[" hoạt động khác nhau và cách sử dụng của chúng phải nhất quán.
[ "$var" = ".."]
thay vì ==
, trong khi ở C, nó sẽ chỉ định thay vì kiểm tra (và là một nguyên nhân phổ biến của lỗi) ... tại sao lại không 't test
sử dụng ==
thay vì =
? có ai biết?
/usr/bin/[
không phải là một liên kết tượng trưng cho /usr/bin/test
và hơn thế nữa: các chương trình này thậm chí có một vài kích cỡ khác nhau!
)
là một phần của case
cú pháp câu lệnh để kết thúc một dòng trường hợp. Nó không có dấu ngoặc đơn mở. Điều này đã ném tôi đi ngay lần đầu tiên tôi nhìn thấy nó.
Chân đế
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
Dấu ngoặc nhọn
${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
Dấu ngoặc
( 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
Dấu ngoặc kép
(( 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)
không liên quan đến cú pháp bash. Nó là một phần của cú pháp Makefile .
$(varname)
không có liên quan đến cú pháp bash trong trường hợp của bạn.
Tôi chỉ muốn thêm chúng từ 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}
hiển thị ba, vì phần tử đầu tiên ARRAY
chứa ba ký tự, không phải vì nó chứa ba phần tử! Để in số lượng phần tử sử dụng echo ${#ARRAY[@]}
.
${TEST:-test}
bằng $TEST
nếu biến TEST
tồn tại, nếu không, nó chỉ trả về chuỗi "test". Có một phiên bản khác thậm chí còn nhiều hơn: ${TEST:=test}
--- cũng tương đương với $TEST
nếu TEST tồn tại, nhưng bất cứ khi nào không có, nó sẽ tạo biến TEST
và gán giá trị "kiểm tra" và cũng trở thành giá trị của toàn bộ biểu thức.
Sự khác biệt giữa thử nghiệm , [ và [[ được giải thích rất chi tiết trong BashFAQ .
Để cắt ngắn một câu chuyện dài: kiểm tra thực hiện cú pháp cũ, di động của lệnh. Trong hầu hết tất cả các shell (shell Bourne lâu đời nhất là ngoại lệ), [là một từ đồng nghĩa để kiểm tra (nhưng yêu cầu một đối số cuối cùng là]). Mặc dù tất cả các shell hiện đại đều có các triển khai tích hợp của [, nhưng thường vẫn có một tệp thực thi bên ngoài của tên đó, ví dụ / bin / [.
[[là phiên bản cải tiến mới của nó, là một từ khóa, không phải là một chương trình. Điều này có tác dụng có lợi cho sự dễ sử dụng, như được hiển thị dưới đây. [[được hiểu bởi KornShell và BASH (ví dụ 2.03), nhưng không phải bởi POSIX hoặc BourneShell cũ.
Và kết luận:
Khi nào thì lệnh kiểm tra mới [[nên được sử dụng và khi nào lệnh cũ [? Nếu tính di động đối với BourneShell là một mối quan tâm, nên sử dụng cú pháp cũ. Mặt khác, tập lệnh yêu cầu BASH hoặc KornShell, cú pháp mới linh hoạt hơn nhiều.
Dấu ngoặc đơn ()
đang được sử dụng trong định nghĩa hàm:
function_name () { command1 ; command2 ; }
Đó là lý do bạn phải thoát dấu ngoặc ngay cả trong các tham số lệnh:
$ 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
. Xem 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