ใน Bash ความแตกต่างระหว่างเครื่องหมายคำพูดเดี่ยว ( ''
) และเครื่องหมายคำพูดคู่ ( ""
) คืออะไร?
ใน Bash ความแตกต่างระหว่างเครื่องหมายคำพูดเดี่ยว ( ''
) และเครื่องหมายคำพูดคู่ ( ""
) คืออะไร?
คำตอบ:
เครื่องหมายคำพูดเดี่ยวจะไม่สอดแทรกอะไร แต่เครื่องหมายคำพูดคู่จะ ตัวอย่างเช่น: ตัวแปรแบคทีก, \
หนีบางอย่างฯลฯ
ตัวอย่าง:
$ echo "$(echo "upg")"
upg
$ echo '$(echo "upg")'
$(echo "upg")
คู่มือ Bash มีสิ่งนี้ที่จะกล่าวว่า:
การใส่อักขระในเครื่องหมายคำพูดเดี่ยว (
'
) จะเก็บค่าตามตัวอักษรของแต่ละอักขระไว้ในเครื่องหมายคำพูด เครื่องหมายคำพูดเดี่ยวอาจไม่เกิดขึ้นระหว่างเครื่องหมายคำพูดเดี่ยวแม้ว่าจะนำหน้าด้วยเครื่องหมายทับขวาล้อมรอบตัวอักษรในคำพูดคู่ (
"
) เก็บรักษามูลค่าที่แท้จริงของตัวละครทุกตัวที่อยู่ในคำพูดที่มีข้อยกเว้นของ$
,`
, และเมื่อการขยายตัวประวัติถูกเปิดใช้งาน\
!
ตัวละคร$
และ`
รักษาความหมายพิเศษไว้ในเครื่องหมายคำพูดคู่ (ดูการขยายเชลล์ ) เครื่องหมายยังคงมีความหมายพิเศษเฉพาะเมื่อตามด้วยหนึ่งในตัวละครต่อไปนี้:$
,`
,"
,\
หรือขึ้นบรรทัดใหม่ ภายในเครื่องหมายคำพูดคู่เครื่องหมายแบ็กสแลชที่ตามด้วยหนึ่งในอักขระเหล่านี้จะถูกลบออก แบ็กสแลชที่นำหน้าอักขระที่ไม่มีความหมายพิเศษจะไม่มีการแก้ไข เครื่องหมายคำพูดคู่อาจถูกอ้างอิงภายในเครื่องหมายคำพูดคู่โดยนำหน้าด้วยเครื่องหมายทับขวา หากเปิดใช้งานการขยายประวัติจะดำเนินการเว้นแต่ว่า!
เครื่องหมายอัญประกาศคู่ปรากฏขึ้นโดยใช้เครื่องหมายทับขวา แบ็กสแลชก่อนหน้า!
จะไม่ถูกลบออกพารามิเตอร์พิเศษ
*
และ@
มีความหมายพิเศษเมื่ออยู่ในเครื่องหมายคำพูดคู่ (ดูการขยายพารามิเตอร์ของเชลล์ )
git_prompt
ที่คอมไพล์ให้พวกเขาขอแนะนำให้ใช้มันเช่นนี้PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
, คอมไพล์พรอมต์ตามนี้ไม่ควรทำงาน มีบางสิ่งที่พิเศษเกี่ยวกับPS#
ตัวแปรหรือไม่? หรือทำไมมันทำงานถ้ามันไม่ได้ทำการแก้ไข
PS1
ลง ลองecho $PS1
ดูสิ่งที่ฉันหมายถึง แต่PS1
จะถูกประเมินก่อนแสดง (ดูPROMPTING
หัวข้อใน bash manpage) PS1='$X'
การทดสอบนี้ลอง คุณจะไม่มีพรอมต์ จากนั้นเรียกใช้X=foo
และทันใดนั้นข้อความแจ้งของคุณคือ "foo" (ได้PS1
รับการประเมินเมื่อตั้งค่าแทนที่จะแสดงคุณจะยังไม่มีข้อความแจ้ง)
ตอบรับดีมาก ฉันกำลังจัดทำตารางที่ช่วยให้เข้าใจหัวข้อได้อย่างรวดเร็ว คำอธิบายที่เกี่ยวข้องกับตัวแปรที่เรียบง่ายเช่นเดียวกับอาร์เรย์จัดทำดัชนีa
arr
หากเราตั้งไว้
a=apple # a simple variable
arr=(apple) # an indexed array with a single element
แล้วecho
นิพจน์ในคอลัมน์ที่สองเราจะได้ผลลัพธ์ / พฤติกรรมที่แสดงในคอลัมน์ที่สาม คอลัมน์ที่สี่อธิบายพฤติกรรม
# | 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
---+-------------+-------------+--------------------------------------------------------------------
ดูสิ่งนี้ด้วย:
The special parameters * and @ have special meaning when in double quotes
แล้วทำไมจึงเกิด"*"
ผลลัพธ์ขึ้นมา*
?
"$@"
และ"$*"
เป็นการขยายพารามิเตอร์ "@"
และ"*"
ไม่ใช่
echo "\'"
\'
หากคุณอ้างถึงสิ่งที่เกิดขึ้นเมื่อคุณสะท้อนบางสิ่งเครื่องหมายคำพูดเดียวจะสะท้อนสิ่งที่คุณมีระหว่างพวกเขาในขณะที่เครื่องหมายคำพูดคู่จะประเมินตัวแปรระหว่างพวกเขาและส่งออกค่าของตัวแปร
ตัวอย่างเช่นสิ่งนี้
#!/bin/sh
MYVAR=sometext
echo "double quotes gives you $MYVAR"
echo 'single quotes gives you $MYVAR'
จะให้สิ่งนี้:
double quotes gives you sometext
single quotes gives you $MYVAR
คนอื่นอธิบายได้ดีมากและเพียงแค่ต้องการยกตัวอย่างง่ายๆ
สามารถใช้เครื่องหมายคำพูดเดี่ยวล้อมรอบข้อความเพื่อป้องกันเชลล์ไม่ให้ตีความอักขระพิเศษใด ๆ เครื่องหมายดอลลาร์ช่องว่างเครื่องหมายแอมป์แซนด์เครื่องหมายดอกจันและอักขระพิเศษอื่น ๆ จะถูกละเว้นทั้งหมดเมื่ออยู่ในเครื่องหมายคำพูดเดี่ยว
$ echo 'All sorts of things are ignored in single quotes, like $ & * ; |.'
มันจะให้สิ่งนี้:
All sorts of things are ignored in single quotes, like $ & * ; |.
สิ่งเดียวที่ไม่สามารถใส่ในเครื่องหมายคำพูดเดียวคือเครื่องหมายคำพูดเดี่ยว
เครื่องหมายคำพูดคู่ทำหน้าที่คล้ายกับเครื่องหมายคำพูดเดี่ยวยกเว้นเครื่องหมายคำพูดคู่ยังอนุญาตให้เชลล์ตีความเครื่องหมายดอลลาร์เครื่องหมายคำพูดหลังและแบ็กสแลช เป็นที่ทราบกันแล้วว่าแบ็กสแลชป้องกันไม่ให้มีการตีความอักขระพิเศษเพียงตัวเดียว สิ่งนี้มีประโยชน์ในเครื่องหมายคำพูดคู่หากจำเป็นต้องใช้เครื่องหมายดอลลาร์เป็นข้อความแทนที่จะเป็นตัวแปร นอกจากนี้ยังอนุญาตให้ใช้อัญประกาศคู่เพื่อไม่ให้ถูกตีความว่าเป็นจุดสิ้นสุดของสตริงที่ยกมา
$ echo "Here's how we can use single ' and double \" quotes within double quotes"
มันจะให้สิ่งนี้:
Here's how we can use single ' and double " quotes within double quotes
อาจสังเกตได้ว่าเครื่องหมายอัญประกาศเดี่ยวซึ่งจะตีความได้ว่าเป็นจุดเริ่มต้นของสตริงที่ยกมานั้นจะถูกละเว้นภายในเครื่องหมายคำพูดคู่ อย่างไรก็ตามตัวแปรถูกตีความและทดแทนด้วยค่าภายในเครื่องหมายคำพูดคู่
$ echo "The current Oracle SID is $ORACLE_SID"
มันจะให้สิ่งนี้:
The current Oracle SID is test
เครื่องหมายคำพูดย้อนกลับไม่เหมือนคำพูดเดียวหรือสองคำ แทนที่จะใช้เพื่อป้องกันการตีความตัวอักษรพิเศษเครื่องหมายคำพูดด้านหลังบังคับให้มีการดำเนินการตามคำสั่งที่แนบมาด้วย หลังจากรันคำสั่งที่ล้อมรอบเอาต์พุตของพวกเขาจะถูกแทนที่ด้วยเครื่องหมายคำพูดด้านหลังในบรรทัดต้นฉบับ นี่จะชัดเจนขึ้นด้วยตัวอย่าง
$ today=`date '+%A, %B %d, %Y'`
$ echo $today
มันจะให้สิ่งนี้:
Monday, September 28, 2015
มีความแตกต่างที่ชัดเจนระหว่างการใช้งานของเป็นและ' '
" "
เมื่อ' '
ใช้กับสิ่งใดก็ตามจะไม่มี "การแปลงหรือการแปล" ทำ มันถูกพิมพ์ตามที่เป็น
ด้วย" "
สิ่งที่มันล้อมรอบคือ "แปลหรือแปลง" เป็นค่าของมัน
โดยการแปล / การแปลงฉันหมายถึงสิ่งต่อไปนี้: สิ่งใดก็ตามที่อยู่ในเครื่องหมายคำพูดเดียวจะไม่ถูก "แปล" เป็นค่าของพวกเขา พวกเขาจะต้องดำเนินการตามที่พวกเขาอยู่ในคำพูด ตัวอย่าง: a=23
จากนั้นecho '$a'
จะสร้าง$a
เอาต์พุตมาตรฐาน ในขณะที่echo "$a"
จะผลิต23
ออกมาตรฐาน
เนื่องจากนี่คือคำตอบที่แท้จริงเมื่อจัดการกับคำพูดในbash
ฉันจะเพิ่มจุดอีกพลาดในคำตอบข้างต้นเมื่อจัดการกับตัวดำเนินการทางคณิตศาสตร์ในเปลือก
bash
เปลือกสนับสนุนทั้งสองวิธีการทำดำเนินการทางคณิตศาสตร์อย่างใดอย่างหนึ่งที่กำหนดโดยในตัวlet
คำสั่งและ$((..))
ผู้ประกอบการ อดีตประเมินการแสดงออกทางคณิตศาสตร์ในขณะที่หลังมีมากกว่าคำสั่งผสม
สิ่งสำคัญคือต้องเข้าใจว่านิพจน์ทางคณิตศาสตร์ที่ใช้กับlet
การแยกคำการขยายชื่อพา ธ เหมือนกับคำสั่งเชลล์อื่น ๆ การอ้างและการหลบหนีที่เหมาะสมจะต้องทำ
ดูตัวอย่างนี้เมื่อใช้ let
let 'foo = 2 + 1'
echo $foo
3
การใช้เครื่องหมายอัญประกาศเดี่ยวที่นี่ก็ใช้ได้จริงที่นี่เนื่องจากไม่จำเป็นต้องขยายตัวแปรที่นี่พิจารณากรณีของ
bar=1
let 'foo = $bar + 1'
จะล้มเหลวอย่างน่าสังเวชเช่น $bar
เครื่องหมายคำพูดเดี่ยวภายใต้จะไม่ขยายและจำเป็นต้องมีเครื่องหมายคำพูดคู่เป็น
let 'foo = '"$bar"' + 1'
นี่ควรเป็นหนึ่งในเหตุผลที่$((..))
ควรพิจารณามากกว่าการใช้let
ควรได้รับการพิจารณามากกว่าการใช้เนื่องจากภายในเนื้อหาไม่ได้ขึ้นอยู่กับการแยกคำ ตัวอย่างก่อนหน้านี้การใช้let
สามารถเขียนเป็น
(( bar=1, foo = bar + 1 ))
$((..))
โดยไม่ต้องใส่เครื่องหมายคำพูดเดียวแม้ว่า$((..))
สามารถใช้กับเครื่องหมายคำพูดคู่ได้ แต่ก็ไม่มีจุดประสงค์เนื่องจากผลลัพธ์ไม่สามารถทำได้มีเนื้อหาที่ต้องมีเครื่องหมายคำพูดคู่ เพียงตรวจสอบให้แน่ใจว่ามันไม่ได้ยกมาเดี่ยว
printf '%d\n' '$((1+1))'
-bash: printf: $((1+1)): invalid number
printf '%d\n' $((1+1))
2
printf '%d\n' "$((1+1))"
2
อาจเป็นกรณีพิเศษบางประการของการใช้ตัว$((..))
ดำเนินการภายในสตริงที่ยกมาเดี่ยวคุณต้องแทรกเครื่องหมายอัญประกาศในลักษณะที่ตัวดำเนินการอาจไม่ได้ใส่เครื่องหมายคำพูดหรือเครื่องหมายอัญประกาศ เช่นพิจารณากรณีเมื่อคุณคาดว่าจะใช้ตัวดำเนินการภายในcurl
คำสั่งเพื่อส่งต่อตัวนับทุกครั้งที่มีการร้องขอให้ทำ
curl http://myurl.com --data-binary '{"requestCounter":'"$((reqcnt++))"'}'
สังเกตเห็นการใช้เครื่องหมายคำพูดคู่ซ้อนภายในโดยที่สตริงตัวอักษร$((reqcnt++))
ถูกส่งผ่านไปยังrequestCounter
เขตข้อมูล
$((...))
เช่นกัน อาจเป็น "หวาดระแวง" เล็กน้อยและไม่น่าเป็นไปได้ที่จะIFS=0
เป็นตัวอย่าง แต่แน่นอนว่ามันเป็นไปไม่ได้อย่างแน่นอน :)
$[[...]]
ไวยากรณ์ดั้งเดิมแต่บางทีคุณอาจถูกลืม