ฉันเขียนได้
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
ผลลัพธ์ที่ได้สำหรับฉันทุกคนดูเหมือนจะเหมือนกัน ทำไมฉันต้องเขียนอย่างใดอย่างหนึ่ง? เหล่านี้ไม่ใช่พกพา / POSIX?
ฉันเขียนได้
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
ผลลัพธ์ที่ได้สำหรับฉันทุกคนดูเหมือนจะเหมือนกัน ทำไมฉันต้องเขียนอย่างใดอย่างหนึ่ง? เหล่านี้ไม่ใช่พกพา / POSIX?
คำตอบ:
VAR=$VAR1
VAR=${VAR1}
เป็นรุ่นที่เรียบง่ายของ มีสิ่งที่สองที่สามารถทำได้ที่สิ่งแรกไม่สามารถทำได้เช่นอ้างอิงดัชนีอาร์เรย์ (ไม่ใช่แบบพกพา) หรือลบสตริงย่อย (POSIX-portable) ดูส่วนเพิ่มเติมเกี่ยวกับตัวแปรของ Bash Guide สำหรับผู้เริ่มต้นและการขยายพารามิเตอร์ในข้อมูลจำเพาะ POSIX
การใช้เครื่องหมายคำพูดรอบ ๆ ตัวแปรเหมือนในrm -- "$VAR1"
หรือrm -- "${VAR}"
เป็นความคิดที่ดี สิ่งนี้ทำให้เนื้อหาของตัวแปรเป็นหน่วยอะตอมมิก หากค่าตัวแปรมีช่องว่าง (เช่นตัวอักษรใน$IFS
ตัวแปรพิเศษช่องว่างโดยค่าเริ่มต้น) หรือตัวอักษรกลมและคุณไม่พูดมันแล้วแต่ละคำจะถูกพิจารณาสำหรับการสร้างชื่อไฟล์ (กลม) ซึ่งการขยายตัวทำให้ขัดแย้งกับสิ่งที่คุณ กำลังทำ
$ find .
.
./*r*
./-rf
./another
./filename
./spaced filename
./another spaced filename
./another spaced filename/x
$ var='spaced filename'
# usually, 'spaced filename' would come from the output of some command and you weren't expecting it
$ rm $var
rm: cannot remove 'spaced': No such file or directory
# oops! I just ran 'rm spaced filename'
$ var='*r*'
$ rm $var
# expands to: 'rm' '-rf' '*r*' 'another spaced filename'
$ find .
.
./another
./spaced filename
./another spaced filename
$ var='another spaced filename'
$ rm -- "$var"
$ find .
.
./another
./spaced filename
เกี่ยวกับการพกพา: ตามPOSIX.1-2008 ส่วน 2.6.2การจัดฟันแบบหยิกเป็นทางเลือก
var1=$var
การขยายให้ข้อผิดพลาดหรือไม่?
export VAR=$VAR1
ส่วนใหญ่รวมทั้ง สำหรับวงเล็บปีกกามันเป็นทางเลือก (ตรวจสอบย่อหน้าที่สี่ของส่วนที่คุณอ้างถึงนี่เป็นกรณีในเชลล์ POSIX และ POSIX ทั้งหมด)
${VAR}
และ$VAR
เทียบเท่า สำหรับการขยายตัวแปรธรรมดาเหตุผลเดียวที่จะใช้${VAR}
คือเมื่อการแยกวิเคราะห์จะจับอักขระจำนวนมากเกินไปในชื่อตัวแปรดังเช่นใน${VAR1}_$VAR2
(ซึ่งไม่มีเครื่องหมายวงเล็บปีกกาจะเทียบเท่า${VAR1_}$VAR2
) ขยายประดับส่วนใหญ่ ( ${VAR:=default}
, ${VAR#prefix}
... ) ต้องจัดฟัน
ในการกำหนดตัวแปร, การแยกฟิลด์ (เช่นการแยกที่ช่องว่างในค่า) และการขยายชื่อพา ธ (เช่น globbing) ถูกปิดดังนั้นจึงVAR=$VAR1
เทียบเท่ากับVAR="$VAR1"
ใน POSIX เชลล์ทั้งหมดและใน POSIX SH ทั้งหมดที่ฉันเคยได้ยิน . (การอ้างอิง POSIX: คำสั่งง่าย ๆ ) ด้วยเหตุผลเดียวกันที่VAR=*
เชื่อถือได้กำหนดVAR
ที่จะสายอักขระตัวอักษร*
; แน่นอนVAR=a b
ชุดVAR
ไปa
ตั้งแต่b
เป็นคำที่แยกจากกันในสถานที่แรก โดยทั่วไปการพูดอัญประกาศคู่ไม่จำเป็นโดยที่ไวยากรณ์เชลล์คาดว่าจะมีคำเดียวตัวอย่างเช่นในcase … in
(แต่ไม่ใช่ในรูปแบบ) แต่ถึงแม้คุณจะต้องระวัง: เช่น POSIX ระบุว่าเป้าหมายการเปลี่ยนเส้นทาง ( >$filename
) ไม่จำเป็นต้องมีการอ้างถึงในสคริปต์ แต่เชลล์บางตัวที่รวมถึง bash นั้นจำเป็นต้องมีเครื่องหมายคำพูดคู่แม้ในสคริปต์ ดูเมื่อมีความจำเป็นต้องใช้การอ้างอิงสองครั้ง? เพื่อการวิเคราะห์ที่ละเอียดยิ่งขึ้น
คุณจำเป็นต้องใส่เครื่องหมายอัญประกาศคู่ในกรณีอื่น ๆ โดยเฉพาะในexport VAR="${VAR1}"
(ซึ่งสามารถเขียนได้เท่ากันexport "VAR=${VAR1}"
) ในเชลล์จำนวนมาก (POSIX เปิดเคสนี้ไว้) ความคล้ายคลึงกันของคดีนี้ที่มีการมอบหมายอย่างง่ายและลักษณะกระจัดกระจายของรายการคดีที่คุณไม่ต้องการอัญประกาศเป็นเหตุผลที่ฉันแนะนำให้ใช้เครื่องหมายคำพูดคู่เว้นแต่ว่าคุณต้องการแยกและกลม
IFS
ตัวละครใด ๆเพราะฉันอยากอยู่ในนิสัย ข้อยกเว้นเดียวคือฉันไม่ได้อ้างอิงค่าเมื่อทำการกำหนดตัวแปร (ยกเว้นกรณีจำเป็นเช่นเมื่อค่ามีช่องว่าง) FOO=$(BAR=$(BAZ=blah; printf %s "${BAZ}"); printf %s "${BAR}")
นี้จะทำให้การแก้ไขไวยากรณ์ไฮไลท์มีประโยชน์มากขึ้นเมื่อมีการแทนคำสั่งเช่น แทนที่จะทำทุกอย่างให้เป็นสี "สตริง" ฉันได้รับการเน้นไวยากรณ์ของรหัสที่ซ้อนกัน นี่คือเหตุผลที่ฉันหลีกเลี่ยง backticks
>$file
ตกลงในสคริปต์ POSIX จะไม่ทุบตีแม้ว่าจะไม่ใช่แบบโต้ตอบ (ยกเว้นว่ามีการบังคับใช้ POSIX $POSIXLY_CORRECT
หรือ--posix
... )
VAR=$VAR1
บางครั้งฉันก็แปลกใจด้วยlocal VAR=$VAR1
ซึ่งฉันจำได้ว่าทำงานแตกต่างกันในบางประเด็นอย่างน้อยเปลือกหอยบางอย่าง แต่ตู้เอทีเอ็มฉันไม่สามารถทำซ้ำความแตกต่าง
local VAR=$VAR1
เป็นเหมือนexport VAR=$VAR1
มันขึ้นอยู่กับเปลือก
พิจารณาว่าการใช้เครื่องหมายคำพูดคู่ใช้สำหรับการขยายตัวของตัวแปรและการใช้เครื่องหมายคำพูดเดี่ยวเพื่อการอ้างอิงที่แข็งแกร่งเช่นการขยายตัวของ Sans
this='foo'
that='bar'
these="$this"
those='$that'
for item in "$this" "$that" "$these" "$those"; do echo "$item"; done
foo
bar
foo
$that
มันอาจจะคุ้มค่าที่จะพูดถึงว่าคุณควรใช้ใบเสนอราคาทุกที่ที่เป็นไปได้ด้วยเหตุผลหลายประการซึ่งเป็นข้อปฏิบัติที่ดีที่สุดและเพื่อให้สามารถอ่านได้ นอกจากนี้เนื่องจาก Bash นั้นเล่นโวหารในบางครั้งและบ่อยครั้งสำหรับวิธีที่ไร้เหตุผลหรือไม่มีเหตุผล / ไม่คาดคิดและการเปลี่ยนแปลงคำพูดเป็นการคาดการณ์ที่ชัดเจน
และในขณะที่มันถูกกฎหมายอย่างสมบูรณ์ที่จะไม่พูดและจะทำงานในกรณีส่วนใหญ่ฟังก์ชั่นที่ให้ไว้เพื่อความสะดวกและอาจพกพาน้อย การปฏิบัติอย่างเป็นทางการที่รับประกันว่าจะสะท้อนให้เห็นถึงความตั้งใจและความคาดหวังคือการพูด
ตอนนี้ให้พิจารณาด้วยว่าการสร้าง"${somevar}"
จะใช้สำหรับการดำเนินการทดแทน กรณีการใช้งานหลายอย่างเช่นการเปลี่ยนและอาร์เรย์
thisfile='foobar.txt.bak'
foo="${thisfile%.*}" # removes shortest part of value in $thisfile matching after '%' from righthand side
bar="${thisfile%%.*}" # removes longest matching
for item in "$foo" "$bar"; do echo "$item"; done
foobar.txt
foobar
foobar='Simplest, least effective, least powerful'
# ${var/find/replace_with}
foo="${foobar/least/most}" #single occurrence
bar="${foobar//least/most}" #global occurrence (all)
for item in "$foobar" "$foo" "$bar"; do echo "$item"; done
Simplest, least effective, least powerful
Simplest, most effective, least powerful
Simplest, most effective, most powerful
mkdir temp
# create files foo.txt, bar.txt, foobar.txt in temp folder
touch temp/{foo,bar,foobar}.txt
# alpha is array of output from ls
alpha=($(ls temp/*))
echo "$alpha" # temp/foo.txt
echo "${alpha}" # temp/foo.txt
echo "${alpha[@]}" # temp/bar.txt temp/foobar.txt temp/foo.txt
echo "${#alpha}" # 12 # length of first element (implicit index [0])
echo "${#alpha[@]}" # 3 # number of elements
echo "${alpha[1]}" # temp/foobar.txt # second element
echo "${#alpha[1])" # 15 # length of second element
for item in "${alpha[@]}"; do echo "$item"; done
temp/bar.txt
temp/foobar.txt
temp/foo.txt
ทั้งหมดนี้เป็นเพียงการเกาพื้นผิวของโครงสร้างการ "${var}"
ทดแทน การอ้างอิงที่ชัดเจนสำหรับการสคริปต์เชลล์ Bash คือการอ้างอิงออนไลน์แบบเรียลไทม์, TLDP โครงการเอกสารลินุกซ์https://www.tldp.org/LDP/abs/html/parameter-substitution.html
ls -la
lrwxrwxrwx. 1 root root 31 Nov 17 13:13 prodhostname
lrwxrwxrwx. 1 root root 33 Nov 17 13:13 testhostname
lrwxrwxrwx. 1 root root 32 Nov 17 13:13 justname
จบแล้ว:
env=$1
if [ ! -f /dirname/${env}hostname ]
มูลค่าการกล่าวขวัญเป็นตัวอย่างที่ชัดเจนของการใช้ curlies