ฉันเขียนได้
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
ผลลัพธ์ที่ได้สำหรับฉันทุกคนดูเหมือนจะเหมือนกัน ทำไมฉันต้องเขียนอย่างใดอย่างหนึ่ง? เหล่านี้ไม่ใช่พกพา / POSIX?
ฉันเขียนได้
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
ผลลัพธ์ที่ได้สำหรับฉันทุกคนดูเหมือนจะเหมือนกัน ทำไมฉันต้องเขียนอย่างใดอย่างหนึ่ง? เหล่านี้ไม่ใช่พกพา / POSIX?
คำตอบ:
VAR=$VAR1VAR=${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