ฉันเขียนสคริปต์ที่สามารถสร้างข้อโต้แย้งเหล่านั้นสำหรับฉันด้วยคำพูด
หากมีการเสนอเอาท์พุทของเชลล์อย่างเหมาะสมและคุณเชื่อใจในเอาต์พุตคุณก็สามารถรันeval
มันได้
สมมติว่าคุณมีเชลล์ที่สนับสนุนอาร์เรย์คุณควรใช้เชลล์เพื่อเก็บอาร์กิวเมนต์ที่คุณได้รับ
หาก./gen_args.sh
ผลิตออกมาเช่น'foo bar' '*' asdf
นั้นเราสามารถเรียกใช้eval "args=( $(./gen_args.sh) )"
เพื่อเติมอาร์เรย์ที่เรียกว่าargs
มีผล ที่จะเป็นสามองค์ประกอบfoo bar
, ,*
asdf
เราสามารถใช้"${args[@]}"
ตามปกติเพื่อขยายองค์ประกอบอาร์เรย์เป็นรายบุคคล:
$ eval "args=( $(./gen_args.sh) )"
$ for var in "${args[@]}"; do printf ":%s:\n" "$var"; done
:foo bar:
:*:
:asdf:
(สังเกตเครื่องหมายคำพูด. "${array[@]}"
ขยายไปยังองค์ประกอบทั้งหมดเป็นอาร์กิวเมนต์ที่แตกต่างที่ไม่ได้แก้ไขโดยไม่ต้องใส่เครื่องหมายอัญประกาศองค์ประกอบอาเรย์อาจมีการแบ่งคำดูเช่นหน้า Arays ใน BashGuide )
อย่างไรก็ตาม , eval
มีความสุขจะทำงานแทนเปลือกใด ๆ ดังนั้นในการส่งออกจะขยายตัวไปยังไดเรกทอรีที่บ้านของคุณและแทนคำสั่งจริงจะเรียกใช้คำสั่งในเปลือกทำงาน$HOME
eval
ผลลัพธ์ของ"$(date >&2)"
จะสร้างองค์ประกอบอาเรย์ที่ว่างเปล่าหนึ่งชิ้นและพิมพ์วันที่ปัจจุบันบน stdout นี่เป็นข้อกังวลหากgen_args.sh
ได้รับข้อมูลจากแหล่งที่ไม่น่าเชื่อถือเช่นโฮสต์อื่นผ่านเครือข่ายชื่อไฟล์ที่สร้างโดยผู้ใช้รายอื่น ผลลัพธ์อาจรวมถึงคำสั่งโดยพลการ (หากget_args.sh
ตัวเองเป็นอันตรายก็ไม่จำเป็นต้องส่งออกอะไรก็สามารถเรียกใช้คำสั่งที่เป็นอันตรายโดยตรง)
อีกทางเลือกหนึ่งในการอ้างอิงเชลล์ซึ่งเป็นการยากที่จะแยกวิเคราะห์โดยไม่ต้องใช้ eval คือการใช้อักขระอื่น ๆ เป็นตัวคั่นในเอาต์พุตของสคริปต์ของคุณ คุณจะต้องเลือกอย่างใดอย่างหนึ่งที่ไม่จำเป็นในข้อโต้แย้งที่เกิดขึ้นจริง
ลองเลือกและมีการส่งออกสคริปต์#
foo bar#*#asdf
ตอนนี้เราสามารถใช้unquotedการขยายตัวของคำสั่งที่จะแยกผลลัพธ์ของคำสั่งที่จะโต้แย้ง
$ IFS='#' # split on '#' signs
$ set -f # disable globbing
$ args=( $( ./gen_args3.sh ) ) # assign the values to the array
$ for var in "${args[@]}"; do printf ":%s:\n" "$var"; done
:foo bar:
:*:
:asdf:
คุณจะต้องIFS
กลับมาใหม่ในภายหลังหากคุณขึ้นอยู่กับการแยกคำที่อื่นในสคริปต์ ( unset IFS
ควรใช้เพื่อทำให้เป็นค่าเริ่มต้น) และใช้set +f
ถ้าคุณต้องการใช้การแปลในภายหลัง
หากคุณไม่ได้ใช้ Bash หรือเชลล์อื่น ๆ ที่มีอาร์เรย์คุณสามารถใช้พารามิเตอร์ตำแหน่งสำหรับสิ่งนั้นได้ แทนที่args=( $(...) )
ด้วยset -- $(./gen_args.sh)
และใช้"$@"
แทน"${args[@]}"
แล้ว (ที่นี่เช่นกันคุณต้องใส่เครื่องหมายอัญประกาศ"$@"
มิฉะนั้นพารามิเตอร์ตำแหน่งจะขึ้นอยู่กับการแยกคำ)
eval
สามารถใช้งานได้ แต่โดยทั่วไปจะไม่แนะนำxargs
เป็นสิ่งที่ต้องพิจารณาเช่นกัน