Câu trả lời:
Dấu ngoặc đơn sẽ không nội suy bất cứ điều gì, nhưng dấu ngoặc kép sẽ. Ví dụ: biến, backticks, \
thoát nhất định , v.v.
Thí dụ:
$ echo "$(echo "upg")"
upg
$ echo '$(echo "upg")'
$(echo "upg")
Hướng dẫn Bash có điều này để nói:
Các ký tự kèm theo trong dấu ngoặc đơn (
'
) giữ nguyên giá trị bằng chữ của mỗi ký tự trong dấu ngoặc kép. Một trích dẫn có thể không xảy ra giữa các trích dẫn đơn, ngay cả khi trước dấu gạch chéo ngược.Kèm theo ký tự trong dấu ngoặc kép (
"
) giữ gìn giá trị văn chương của tất cả các ký tự trong dấu ngoặc kép, với ngoại lệ của$
,`
,\
, và, khi mở rộng lịch sử được kích hoạt,!
. Các ký tự$
và`
giữ lại ý nghĩa đặc biệt của chúng trong dấu ngoặc kép (xem Mở rộng Shell ). Các dấu chéo ngược vẫn giữ được ý nghĩa đặc biệt của nó chỉ khi theo sau là một trong những nhân vật sau:$
,`
,"
,\
hoặc dòng mới. Trong dấu ngoặc kép, dấu gạch chéo ngược được theo sau bởi một trong các ký tự này sẽ bị xóa. Dấu gạch chéo ngược trước các ký tự không có ý nghĩa đặc biệt sẽ không được sửa đổi. Một trích dẫn kép có thể được trích dẫn trong dấu ngoặc kép bằng cách đặt trước nó bằng dấu gạch chéo ngược. Nếu được bật, mở rộng lịch sử sẽ được thực hiện trừ khi!
xuất hiện trong dấu ngoặc kép được sử dụng dấu gạch chéo ngược. Dấu gạch chéo ngược trước!
không được loại bỏ.Các tham số đặc biệt
*
và@
có ý nghĩa đặc biệt khi trong dấu ngoặc kép (xem Mở rộng tham số Shell ).
git_prompt
git cung cấp họ đề nghị sử dụng nó như thế này PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
, nhắc nhở git , theo điều này không nên làm việc. Có điều gì đặc biệt về các PS#
biến? hoặc tại sao nó hoạt động nếu nó không thực hiện phép nội suy.
PS1
. Hãy thử echo $PS1
xem tôi muốn nói gì Nhưng PS1
được đánh giá trước khi được hiển thị (xem PROMPTING
phần trong trang bash). Để kiểm tra điều này, hãy thử PS1='$X'
. Bạn sẽ không có lời nhắc. Sau đó chạy X=foo
và đột nhiên lời nhắc của bạn là "foo" (đã PS1
được đánh giá khi được đặt thay vì hiển thị, bạn vẫn không có dấu nhắc).
Các câu trả lời được chấp nhận là rất tốt. Tôi đang làm một bảng giúp hiểu nhanh về chủ đề này. Giải thích liên quan đến một biến đơn giản a
cũng như một mảng được lập chỉ mục arr
.
Nếu chúng ta đặt
a=apple # a simple variable
arr=(apple) # an indexed array with a single element
và sau đó echo
biểu thức trong cột thứ hai, chúng ta sẽ nhận được kết quả / hành vi được hiển thị trong cột thứ ba. Cột thứ tư giải thích hành vi.
# | Expression | Result | Comments
---+-------------+-------------+--------------------------------------------------------------------
1 | "$a" | apple | variables are expanded inside ""
2 | '$a' | $a | variables are not expanded inside ''
3 | "'$a'" | 'apple' | '' has no special meaning inside ""
4 | '"$a"' | "$a" | "" is treated literally inside ''
5 | '\'' | **invalid** | can not escape a ' within ''; use "'" or $'\'' (ANSI-C quoting)
6 | "red$arocks"| red | $arocks does not expand $a; use ${a}rocks to preserve $a
7 | "redapple$" | redapple$ | $ followed by no variable name evaluates to $
8 | '\"' | \" | \ has no special meaning inside ''
9 | "\'" | \' | \' is interpreted inside "" but has no significance for '
10 | "\"" | " | \" is interpreted inside ""
11 | "*" | * | glob does not work inside "" or ''
12 | "\t\n" | \t\n | \t and \n have no special meaning inside "" or ''; use ANSI-C quoting
13 | "`echo hi`" | hi | `` and $() are evaluated inside ""
14 | '`echo hi`' | `echo hi` | `` and $() are not evaluated inside ''
15 | '${arr[0]}' | ${arr[0]} | array access not possible inside ''
16 | "${arr[0]}" | apple | array access works inside ""
17 | $'$a\'' | $a' | single quotes can be escaped inside ANSI-C quoting
18 | "$'\t'" | $'\t' | ANSI-C quoting is not interpreted inside ""
19 | '!cmd' | !cmd | history expansion character '!' is ignored inside ''
20 | "!cmd" | cmd args | expands to the most recent command matching "cmd"
21 | $'!cmd' | !cmd | history expansion character '!' is ignored inside ANSI-C quotes
---+-------------+-------------+--------------------------------------------------------------------
Xem thêm:
The special parameters * and @ have special meaning when in double quotes
vậy "*"
kết quả *
thế nào?
"$@"
và "$*"
là mở rộng tham số. "@"
và "*"
không.
echo "\'"
, trả lại cho tôi \'
.
Nếu bạn đang đề cập đến những gì xảy ra khi bạn lặp lại một cái gì đó, các dấu ngoặc đơn sẽ lặp lại theo nghĩa đen những gì bạn có giữa chúng, trong khi dấu ngoặc kép sẽ đánh giá các biến giữa chúng và đưa ra giá trị của biến.
Ví dụ, cái này
#!/bin/sh
MYVAR=sometext
echo "double quotes gives you $MYVAR"
echo 'single quotes gives you $MYVAR'
sẽ đưa ra điều này:
double quotes gives you sometext
single quotes gives you $MYVAR
Những người khác giải thích rất tốt và chỉ muốn đưa ra với các ví dụ đơn giản.
Dấu ngoặc đơn có thể được sử dụng xung quanh văn bản để ngăn shell diễn giải bất kỳ ký tự đặc biệt nào. Dấu đô la, dấu cách, ký hiệu, dấu hoa thị và các ký tự đặc biệt khác đều bị bỏ qua khi được đặt trong các dấu ngoặc đơn.
$ echo 'All sorts of things are ignored in single quotes, like $ & * ; |.'
Nó sẽ cung cấp cho điều này:
All sorts of things are ignored in single quotes, like $ & * ; |.
Điều duy nhất không thể được đặt trong dấu ngoặc đơn là một trích dẫn.
Dấu ngoặc kép hoạt động tương tự như dấu ngoặc đơn, ngoại trừ dấu ngoặc kép vẫn cho phép trình bao hiểu các dấu đô la, dấu ngoặc kép ngược và dấu gạch chéo ngược. Người ta đã biết rằng dấu gạch chéo ngược ngăn không cho một ký tự đặc biệt nào được giải thích. Điều này có thể hữu ích trong dấu ngoặc kép nếu ký hiệu đô la cần được sử dụng làm văn bản thay vì cho một biến. Nó cũng cho phép các dấu ngoặc kép được thoát để chúng không được hiểu là phần cuối của chuỗi được trích dẫn.
$ echo "Here's how we can use single ' and double \" quotes within double quotes"
Nó sẽ cung cấp cho điều này:
Here's how we can use single ' and double " quotes within double quotes
Cũng có thể nhận thấy rằng dấu nháy đơn, nếu không sẽ được hiểu là phần đầu của chuỗi trích dẫn, bị bỏ qua trong dấu ngoặc kép. Các biến, tuy nhiên, được giải thích và thay thế bằng các giá trị của chúng trong dấu ngoặc kép.
$ echo "The current Oracle SID is $ORACLE_SID"
Nó sẽ cung cấp cho điều này:
The current Oracle SID is test
Báo giá lại hoàn toàn không giống như trích dẫn đơn hoặc đôi. Thay vì được sử dụng để ngăn chặn việc giải thích các ký tự đặc biệt, các trích dẫn ngược thực sự buộc thực thi các lệnh mà chúng kèm theo. Sau khi các lệnh kèm theo được thực thi, đầu ra của chúng được thay thế thay cho dấu ngoặc kép ở dòng ban đầu. Điều này sẽ rõ ràng hơn với một ví dụ.
$ today=`date '+%A, %B %d, %Y'`
$ echo $today
Nó sẽ cung cấp cho điều này:
Monday, September 28, 2015
Có một sự phân biệt rõ ràng giữa việc sử dụng ' '
và " "
.
Khi ' '
được sử dụng xung quanh bất cứ thứ gì, không có "chuyển đổi hoặc dịch" được thực hiện. Nó được in như nó là.
Với " "
, bất cứ thứ gì nó bao quanh, đều được "dịch hoặc biến đổi" thành giá trị của nó.
Bằng cách dịch / chuyển đổi tôi có nghĩa như sau: Bất kỳ điều gì trong dấu ngoặc đơn sẽ không được "dịch" thành giá trị của chúng. Họ sẽ được thực hiện như họ đang ở trong dấu ngoặc kép. Ví dụ : a=23
, sau đó echo '$a'
sẽ sản xuất $a
trên đầu ra tiêu chuẩn. Trong khi đó echo "$a"
sẽ sản xuất 23
trên đầu ra tiêu chuẩn.
Vì đây là câu trả lời thực tế khi xử lý dấu ngoặc kép trong bash
, tôi sẽ thêm một điểm bị bỏ lỡ trong các câu trả lời ở trên, khi xử lý các toán tử số học trong trình bao.
Các bash
vỏ hỗ trợ hai cách thực hiện hành động số học, một định nghĩa bởi được xây dựng trong let
lệnh và các $((..))
nhà điều hành. Cái trước đánh giá một biểu thức số học trong khi cái sau là một câu lệnh ghép.
Điều quan trọng là phải hiểu rằng biểu thức số học được sử dụng với việc let
trải qua quá trình chia tách từ, mở rộng tên đường dẫn giống như bất kỳ lệnh shell nào khác. Vì vậy, trích dẫn thích hợp và thoát cần phải được thực hiện.
Xem ví dụ này khi sử dụng let
let 'foo = 2 + 1'
echo $foo
3
Sử dụng dấu ngoặc đơn ở đây là hoàn toàn tốt ở đây, vì không cần mở rộng biến ở đây, hãy xem xét một trường hợp
bar=1
let 'foo = $bar + 1'
sẽ thất bại thảm hại, vì các $bar
trích dẫn dưới đây sẽ không mở rộng và cần được trích dẫn hai lần như
let 'foo = '"$bar"' + 1'
Đây phải là một trong những lý do, $((..))
nên luôn luôn được xem xét sử dụng let
. Bởi vì bên trong nó, nội dung không chịu sự chia tách từ. Ví dụ trước sử dụng let
có thể được viết đơn giản là
(( bar=1, foo = bar + 1 ))
$((..))
mà không có dấu ngoặc đơnMặc dù $((..))
có thể được sử dụng với dấu ngoặc kép, nhưng không có mục đích nào vì nó không thể chứa nội dung cần trích dẫn kép. Chỉ cần đảm bảo nó không được trích dẫn.
printf '%d\n' '$((1+1))'
-bash: printf: $((1+1)): invalid number
printf '%d\n' $((1+1))
2
printf '%d\n' "$((1+1))"
2
Có thể trong một số trường hợp đặc biệt sử dụng $((..))
toán tử bên trong một chuỗi trích dẫn, bạn cần nội suy các trích dẫn theo cách mà toán tử hoặc không được trích dẫn hoặc dưới dấu ngoặc kép. Ví dụ, hãy xem xét một trường hợp, khi bạn buộc phải sử dụng toán tử bên trong một curl
câu lệnh để vượt qua bộ đếm mỗi khi yêu cầu được thực hiện, hãy làm
curl http://myurl.com --data-binary '{"requestCounter":'"$((reqcnt++))"'}'
Lưu ý việc sử dụng dấu ngoặc kép lồng nhau bên trong, mà không có chuỗi ký tự nào $((reqcnt++))
được truyền vào requestCounter
trường.
$((...))
. Nó có thể là "một chút" hoang tưởng và khá khó có thể có IFS=0
ví dụ, nhưng chắc chắn là không thể :)
$[[...]]
cú pháp kế thừa nhưng có lẽ bạn đã quên nó.