ฉันสามารถละเว้นการเสนอราคาทางด้านขวาของการมอบหมายงานท้องถิ่นได้อย่างปลอดภัยหรือไม่?
function foo {
local myvar=${bar}
stuff()
}
ฉันสนใจเป็นหลักbash
แต่ข้อมูลใด ๆ ในกรณีมุมในเปลือกหอยอื่น ๆ ยินดีต้อนรับ
ฉันสามารถละเว้นการเสนอราคาทางด้านขวาของการมอบหมายงานท้องถิ่นได้อย่างปลอดภัยหรือไม่?
function foo {
local myvar=${bar}
stuff()
}
ฉันสนใจเป็นหลักbash
แต่ข้อมูลใด ๆ ในกรณีมุมในเปลือกหอยอื่น ๆ ยินดีต้อนรับ
คำตอบ:
คำพูดที่มีความจำเป็นในexport foo="$var"
หรือlocal foo="$var"
(หรือreadonly
, typeset
, declare
และตัวแปรอื่น ๆ ประกาศคำสั่ง ) ใน:
dash
sh
ของ NetBSD (ตามเชลล์ Almquist ด้วย)sh
FreeBSD 9.2 หรือเก่ากว่า (ดูการเปลี่ยนแปลงใน 9.3 )yash
zsh
กับรุ่นก่อนหน้า 5.1 ในksh
หรือการsh
จำลอง (หรือสำหรับexport var="$(cmd)"
ตำแหน่งที่zsh
จะทำการแยกคำอื่น ๆ (ไม่โค้ง)มิฉะนั้นการขยายตัวของตัวแปรจะขึ้นอยู่กับการแยกคำและ / หรือการสร้างชื่อไฟล์เหมือนในอาร์กิวเมนต์ใด ๆ กับคำสั่งอื่น ๆ
และไม่จำเป็นใน:
bash
ksh
(การใช้งานทั้งหมด)sh
FreeBSD 9.3 หรือใหม่กว่าsh
(ตั้งแต่ปี 2005)zsh
ในการzsh
แบ่ง + glob ไม่เคยทำกับการขยายพารามิเตอร์ยกเว้นในsh
หรือksh
จำลอง แต่แยก (ไม่ใช่ glob) จะทำเมื่อมีการทดแทนคำสั่ง ตั้งแต่เวอร์ชัน 5.1, export
/ local
และคำสั่งการประกาศอื่น ๆ ได้กลายเป็นคำสั่งคู่คีย์เวิร์ด / builtinเช่นในเชลล์อื่น ๆ ข้างต้นซึ่งหมายความว่าไม่จำเป็นต้องมีการอ้างถึงแม้ในsh
/ ksh
emulation และแม้กระทั่งสำหรับการทดแทนคำสั่ง
มีกรณีพิเศษที่จำเป็นต้องมีการอ้างถึงแม้ในเชลล์เหล่านั้นเช่น:
a="b=some value"
export "$a"
หรืออื่น ๆ โดยทั่วไปถ้ามีอะไรซ้ายของ=
(รวม=
) จะยกมาหรือผลของการขยายตัวของบางอย่าง (เช่นexport 'foo'="$var"
, export foo\="$var"
หรือexport foo$((n+=1))="$var"
(ว่า$((...))
ควรที่จะยกมาจริง) ... ) หรือในคำอื่น ๆ เมื่อการโต้แย้งไปจะไม่กำหนดตัวแปรที่ถูกต้องถ้าเขียนได้โดยไม่ต้องexport
export
หากexport
/ local
ชื่อคำสั่งตัวเองจะยกมา (แม้ในส่วนเช่น"export" a="$b"
, 'ex'port a="$b"
, \export a="$b"
หรือแม้กระทั่ง""export a="$b"
), คำพูดที่อยู่รอบ ๆ$b
ที่มีความจำเป็นยกเว้นใน AT & T และksh
mksh
หาก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
งานที่ได้รับมอบหมายหมายถึงสถานะทางออกของcmd
in 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 พิเศษ)