ขณะที่ฉันใช้ความหมายของคุณฉันไม่เชื่อว่าคำตอบใด ๆ เหล่านี้ถูกต้อง eval
ไม่จำเป็นต้องใช้วิธีการใด ๆ และคุณไม่จำเป็นต้องประเมินตัวแปรของคุณสองเท่า
เป็นความจริง @Gilles เข้ามาใกล้มาก แต่เขาไม่ได้แก้ไขปัญหาของค่านิยมที่อาจเอาชนะได้และวิธีการใช้หากพวกเขาต้องการมากกว่าหนึ่งครั้ง ท้ายที่สุดควรใช้เทมเพลตมากกว่าหนึ่งครั้งใช่ไหม
ฉันคิดว่ามันเป็นเรื่องที่คุณประเมินมันสำคัญมาก พิจารณาสิ่งต่อไปนี้:
TOP
ที่นี่คุณจะตั้งค่าเริ่มต้นและเตรียมพิมพ์เมื่อเรียก ...
#!/bin/sh
_top_of_script_pr() (
IFS="$nl" ; set -f #only split at newlines and don't expand paths
printf %s\\n ${strings}
) 3<<-TEMPLATES
${nl=
}
${PLACE:="your mother's house"}
${EVENT:="the unspeakable."}
${ACTION:="heroin"}
${RESULT:="succeed."}
${strings:="
I went to ${PLACE} and saw ${EVENT}
If you do ${ACTION} you will ${RESULT}
"}
#END
TEMPLATES
กลาง
นี่คือที่คุณกำหนดฟังก์ชั่นอื่น ๆ เพื่อเรียกใช้ฟังก์ชั่นการพิมพ์ของคุณตามผลของพวกเขา ...
EVENT="Disney on Ice."
_more_important_function() { #...some logic...
[ $((1+one)) -ne 2 ] && ACTION="remedial mathematics"
_top_of_script_pr
}
_less_important_function() { #...more logic...
one=2
: "${ACTION:="calligraphy"}"
_top_of_script_pr
}
ด้านล่าง
คุณได้รับการตั้งค่าทั้งหมดแล้วดังนั้นนี่คือที่ที่คุณจะดำเนินการและดึงผลลัพธ์ของคุณ
_less_important_function
: "${PLACE:="the cemetery"}"
_more_important_function
: "${RESULT:="regret it."}"
_less_important_function
ผล
ฉันจะไปทำไมในไม่ช้า แต่การเรียกใช้ข้างต้นสร้างผลลัพธ์ต่อไปนี้:
_less_important_function()'s
วิ่งครั้งแรก:
ฉันไปที่บ้านแม่ของคุณและเห็นDisney on Ice
ถ้าคุณเขียนตัวอักษรคุณจะประสบความสำเร็จ
แล้วก็ _more_important_function():
ฉันไปที่สุสานและเห็น Disney on Ice
หากคุณทำคณิตศาสตร์การแก้ไขคุณจะประสบความสำเร็จ
_less_important_function()
อีกครั้ง:
ฉันไปที่สุสานและเห็น Disney on Ice
หากคุณทำคณิตศาสตร์เพื่อการเยียวยาคุณจะต้องเสียใจ
มันทำงานอย่างไร:
คุณสมบัติที่สำคัญที่นี่เป็นแนวคิดของconditional ${parameter} expansion.
คุณสามารถตั้งค่าตัวแปรให้เป็นค่าเฉพาะถ้ามันเป็น unset หรือ null โดยใช้แบบฟอร์ม:
${var_name
=desired_value}
หากคุณต้องการตั้งค่าเฉพาะตัวแปรที่ไม่มีการตั้งค่าคุณจะละเว้น:colon
และค่า Null จะยังคงเหมือนเดิม
ในขอบเขต:
คุณอาจสังเกตเห็นว่าในตัวอย่างข้างต้น$PLACE
และ$RESULT
ได้รับการเปลี่ยนแปลงเมื่อตั้งค่าผ่านparameter expansion
แม้ว่าจะ_top_of_script_pr()
ถูกเรียกไปแล้วแต่ก็น่าจะตั้งค่าพวกเขาเมื่อมันทำงาน เหตุผลที่ทำให้งานนี้_top_of_script_pr()
เป็น( subshelled )
ฟังก์ชั่น - ฉันใส่มันไว้ในตัวparens
แทนที่จะ{ curly braces }
ใช้กับคนอื่น เพราะมันถูกเรียกใน subshell ทุกตัวแปรที่มันตั้งค่าคือlocally scoped
และเมื่อมันกลับไปที่เปลือกแม่ของมันค่าเหล่านั้นจะหายไป
แต่เมื่อทำการ_more_important_function()
ตั้งค่า$ACTION
มันglobally scoped
จึงส่งผลกระทบต่อ_less_important_function()'s
การประเมินครั้งที่สองของ$ACTION
เพราะ_less_important_function()
ตั้งค่า$ACTION
ผ่านทางเท่านั้น${parameter:=expansion}.
: เป็นโมฆะ
และทำไมฉันถึงใช้:colon?
ดีเวลนำman
หน้าจะบอกคุณว่า: does nothing, gracefully.
คุณเห็นparameter expansion
มันเป็นสิ่งที่มันดูเหมือน - มันexpands
เป็นค่าของ${parameter}.
ดังนั้นเมื่อเราตั้งค่าตัวแปรด้วย${parameter:=expansion}
เราจะทิ้งไว้กับค่าของมัน - ซึ่งเชลล์จะ พยายามเรียกใช้งานในบรรทัด หากมันพยายามที่จะเรียกใช้the cemetery
มันก็จะคายข้อผิดพลาดที่คุณ PLACE="${PLACE:="the cemetery"}"
จะให้ผลลัพธ์ที่เหมือนกัน แต่ก็ยังซ้ำซ้อนในกรณีนี้และฉันต้องการเชลล์: ${did:=nothing, gracefully}.
มันช่วยให้คุณทำสิ่งนี้:
echo ${var:=something or other}
echo $var
something or other
something or other
ที่นี่เอกสาร
และโดยวิธี - คำจำกัดความในบรรทัดของตัวแปร null หรือ unset เป็นสาเหตุที่ทำให้งานต่อไปนี้:
<<HEREDOC echo $yo
${yo=yoyo}
HEREDOC
yoyo
วิธีที่ดีที่สุดในการนึกถึงhere-document
คือเป็นไฟล์จริงสตรีมไปยัง file-descriptor มากขึ้นหรือน้อยลงนั่นคือสิ่งที่พวกเขาเป็น แต่กระสุนที่แตกต่างกันนำพวกเขาไปใช้ต่างกันเล็กน้อย
ไม่ว่าในกรณีใดถ้าคุณไม่ได้อ้างถึง<<LIMITER
คุณจะได้รับมันสตรีมและประเมินผลexpansion.
ดังนั้นการประกาศตัวแปรใน a here-document
can สามารถทำงานได้ แต่ผ่านทางexpansion
ที่ จำกัด ให้คุณตั้งค่าเฉพาะตัวแปรที่ยังไม่ได้ตั้งค่า ยังคงเป็นสิ่งที่เหมาะสมกับความต้องการของคุณอย่างสมบูรณ์ที่สุดเนื่องจากค่าเริ่มต้นของคุณจะถูกตั้งค่าเสมอเมื่อคุณเรียกใช้ฟังก์ชันการพิมพ์แม่แบบ
ทำไมจะไม่ล่ะ eval?
ตัวอย่างที่ฉันนำเสนอให้วิธีการที่ปลอดภัยและมีประสิทธิภาพในการยอมรับparameters.
เพราะมันจัดการกับขอบเขตตัวแปรทุกตัวที่อยู่ในชุดผ่าน${parameter:=expansion}
นั้นสามารถกำหนดได้จากภายนอก ดังนั้นหากคุณใส่ทั้งหมดนี้ไว้ในสคริปต์ชื่อ template_pr.sh แล้ววิ่ง:
% RESULT=something_else template_pr.sh
คุณจะได้รับ:
ฉันไปที่บ้านแม่ของคุณและเห็น Disney on Ice
ถ้าคุณเขียนตัวอักษรคุณจะพบกับบางสิ่งบางอย่าง
ฉันไปที่สุสานและเห็น Disney on Ice
หากคุณทำคณิตศาสตร์เพื่อการแก้ไขคุณจะต้องมีอะไรบางอย่าง
ฉันไปที่สุสานและเห็น Disney on Ice
หากคุณทำคณิตศาสตร์เพื่อการแก้ไขคุณจะต้องมีอะไรบางอย่าง
สิ่งนี้จะไม่ทำงานสำหรับตัวแปรเหล่านั้นที่ตั้งไว้ในสคริปต์อย่างแท้จริงเช่น$EVENT, $ACTION,
และ$one,
แต่ฉันกำหนดเฉพาะสิ่งเหล่านั้นเพื่อแสดงให้เห็นถึงความแตกต่าง
ไม่ว่าในกรณีใดการยอมรับข้อมูลที่ไม่รู้จักลงในevaled
คำสั่งนั้นไม่ปลอดภัยโดยเนื้อแท้ในขณะที่parameter expansion
ถูกออกแบบมาโดยเฉพาะให้ทำ