ฉันสามารถละเว้นการเสนอราคาทางด้านขวาของการมอบหมายงานท้องถิ่นได้อย่างปลอดภัยหรือไม่?
function foo {
local myvar=${bar}
stuff()
}
ฉันสนใจเป็นหลักbashแต่ข้อมูลใด ๆ ในกรณีมุมในเปลือกหอยอื่น ๆ ยินดีต้อนรับ
ฉันสามารถละเว้นการเสนอราคาทางด้านขวาของการมอบหมายงานท้องถิ่นได้อย่างปลอดภัยหรือไม่?
function foo {
local myvar=${bar}
stuff()
}
ฉันสนใจเป็นหลักbashแต่ข้อมูลใด ๆ ในกรณีมุมในเปลือกหอยอื่น ๆ ยินดีต้อนรับ
คำตอบ:
คำพูดที่มีความจำเป็นในexport foo="$var"หรือlocal foo="$var"(หรือreadonly, typeset, declareและตัวแปรอื่น ๆ ประกาศคำสั่ง ) ใน:
dashshของ NetBSD (ตามเชลล์ Almquist ด้วย)shFreeBSD 9.2 หรือเก่ากว่า (ดูการเปลี่ยนแปลงใน 9.3 )yashzshกับรุ่นก่อนหน้า 5.1 ในkshหรือการshจำลอง (หรือสำหรับexport var="$(cmd)"ตำแหน่งที่zshจะทำการแยกคำอื่น ๆ (ไม่โค้ง)มิฉะนั้นการขยายตัวของตัวแปรจะขึ้นอยู่กับการแยกคำและ / หรือการสร้างชื่อไฟล์เหมือนในอาร์กิวเมนต์ใด ๆ กับคำสั่งอื่น ๆ
และไม่จำเป็นใน:
bashksh (การใช้งานทั้งหมด)shFreeBSD 9.3 หรือใหม่กว่าsh(ตั้งแต่ปี 2005)zshในการzshแบ่ง + glob ไม่เคยทำกับการขยายพารามิเตอร์ยกเว้นในshหรือkshจำลอง แต่แยก (ไม่ใช่ glob) จะทำเมื่อมีการทดแทนคำสั่ง ตั้งแต่เวอร์ชัน 5.1, export/ localและคำสั่งการประกาศอื่น ๆ ได้กลายเป็นคำสั่งคู่คีย์เวิร์ด / builtinเช่นในเชลล์อื่น ๆ ข้างต้นซึ่งหมายความว่าไม่จำเป็นต้องมีการอ้างถึงแม้ในsh/ kshemulation และแม้กระทั่งสำหรับการทดแทนคำสั่ง
มีกรณีพิเศษที่จำเป็นต้องมีการอ้างถึงแม้ในเชลล์เหล่านั้นเช่น:
a="b=some value"
export "$a"
หรืออื่น ๆ โดยทั่วไปถ้ามีอะไรซ้ายของ=(รวม=) จะยกมาหรือผลของการขยายตัวของบางอย่าง (เช่นexport 'foo'="$var", export foo\="$var"หรือexport foo$((n+=1))="$var"(ว่า$((...))ควรที่จะยกมาจริง) ... ) หรือในคำอื่น ๆ เมื่อการโต้แย้งไปจะไม่กำหนดตัวแปรที่ถูกต้องถ้าเขียนได้โดยไม่ต้องexportexport
หากexport/ localชื่อคำสั่งตัวเองจะยกมา (แม้ในส่วนเช่น"export" a="$b", 'ex'port a="$b", \export a="$b"หรือแม้กระทั่ง""export a="$b"), คำพูดที่อยู่รอบ ๆ$bที่มีความจำเป็นยกเว้นใน AT & T และkshmksh
หากexport/ localหรือบางส่วนของมันเป็นผลมาจากการขยายตัวบางอย่าง (เช่นในcmd=export; "$cmd" a="$b"หรือแม้กระทั่งexport$(:) a="$b") หรือในสิ่งที่ชอบdryrun=; $dryrun export a="$b") แล้วคำพูดที่มีความจำเป็นในทุกเปลือก
ในกรณีของ> /dev/null export a="$b"จำเป็นต้องมีการเสนอราคาในpdkshและบางส่วนของอนุพันธ์
สำหรับcommand export a="$b", จำเป็นต้องใช้อัญประกาศในทุกเชลล์ แต่mkshและksh93(ด้วยคำเตือนเดียวกันเกี่ยวกับcommandและexportไม่เป็นผลของการขยายตัว)
พวกมันไม่ต้องการในเชลล์เมื่อเขียน:
foo=$var export foo
(ไวยากรณ์นั้นยังเข้ากันได้กับเชลล์เป้าหมาย แต่ในเวอร์ชันล่าสุดzshจะทำงานเฉพาะเมื่ออยู่ในsh/ kshจำลอง)
(โปรดทราบว่าvar=value local varไม่ควรใช้เนื่องจากพฤติกรรมแตกต่างกันไปในแต่ละเชลล์)
นอกจากนี้โปรดทราบว่าการใช้exportงานที่ได้รับมอบหมายหมายถึงสถานะทางออกของcmdin export var="$(cmd)"สูญหาย ทำตามที่export var; var=$(cmd)ไม่มีปัญหา
ยังระวังกรณีพิเศษนี้ด้วยbash:
$ bash -c 'IFS=; export a="$*"; echo "$a"' bash a b
ab
$ bash -c 'IFS=; export a=$*; echo "$a"' bash a b
a b
คำแนะนำของฉันคือการพูดเสมอ
zshคำพูดที่จะจำเป็นสำหรับการlocal foo="$(cmd)"เพราะ wordsplitting ( แต่ไม่ใช่รุ่นชื่อไฟล์) จะดำเนินการสำหรับการแทนคำสั่ง unquoted ( แต่ไม่สำหรับการขยายพารามิเตอร์ unquoted) เว้นแต่KSH_TYPESETจะเปิดใช้งานซึ่งในคำพูดกรณีที่จะไม่จำเป็น ทำให้รู้สึก? ไม่มี? จากนั้นให้พูดทุกอย่างยกเว้นว่าคุณรู้ว่าคุณกำลังทำอะไรอยู่
ฉันมักจะพูดถึงการใช้งานของตัวแปรใด ๆ ที่อาจมีตัวละครเช่นช่องว่างสีขาว มิฉะนั้นคุณจะพบปัญหาเช่นนี้:
#!/bin/bash
bar="hi bye"
function foo {
local myvar=${bar}
printf "%s\n" $myvar
printf "%s\n" "$myvar"
}
foo
การใช้งานตัวแปรในการมอบหมายไม่ปรากฏว่าจำเป็นต้องใช้เครื่องหมายคำพูด แต่เมื่อคุณไปใช้งานเช่นในตัวprintfคุณจะต้องมีการเสนอราคาที่นั่น:
printf "%s\n" "$myvar"
หมายเหตุ:โปรดจำไว้ว่าตัวแปร$IFSคือสิ่งที่ควบคุมว่าอักขระตัวคั่นคืออะไร
IFS The Internal Field Separator that is used for word splitting after
expansion and to split lines into words with the read builtin command.
The default value is ``<space><tab><newline>''.
เมื่อเปิดใช้งานการดีบักใน Bash เราจะเห็นว่าเกิดอะไรขึ้นเบื้องหลัง
$ bash -x cmd.bash
+ bar='hi bye'
+ foo
+ local 'myvar=hi bye'
+ printf '%s\n' hi bye
hi
bye
+ printf '%s\n' 'hi bye'
hi bye
ในข้างต้นเราจะเห็นว่าตัวแปร$barถูกส่งไปได้ดี$myvarแต่แล้วเมื่อเราไปใช้$myvarเราจะต้องมีความรู้ความเข้าใจในเนื้อหาของ$myvarเมื่อเราไปใช้มัน
bashและkshในlocal/ typeset... builtins พิเศษ)