จะเปลี่ยนอาร์กิวเมนต์บรรทัดคำสั่งใน Bash ได้อย่างไร?


98

มีวิธีเปลี่ยนอาร์กิวเมนต์บรรทัดคำสั่งในสคริปต์ Bash หรือไม่? ตัวอย่างเช่นสคริปต์ Bash ถูกเรียกเช่นนี้:

./foo arg1 arg2  

มีวิธีเปลี่ยนค่าของ arg1 ภายในสคริปต์หรือไม่? สิ่งที่ต้องการ:

$1="chintz"

คำตอบ:


154

คุณต้องรีเซ็ตอาร์กิวเมนต์ทั้งหมด ในการเปลี่ยนแปลงเช่น$3:

$ set -- "${@:1:2}" "new" "${@:4}"

โดยพื้นฐานแล้วคุณตั้งค่า อาร์กิวเมนต์ทั้งหมดเป็นค่าปัจจุบันยกเว้นอาร์กิวเมนต์ที่คุณต้องการเปลี่ยนแปลง set --นอกจากนี้ยังมีการระบุโดย POSIX 7

"${@:1:2}"สัญกรณ์มีการขยายไปยังสอง (เพราะฉะนั้น2ในสัญกรณ์) ข้อโต้แย้งตำแหน่งเริ่มต้นจากการชดเชย1(คือ$1) มันเป็นชื่อย่อสำหรับ"$1" "$2"ในกรณีนี้ "${17}"แต่มันเป็นประโยชน์มากขึ้นเมื่อคุณต้องการที่จะเปลี่ยนเช่น


1
ดังนั้นในการเปลี่ยน $ 3 ฉันต้องเปลี่ยน $ 1 และ $ 2 ด้วยใช่ไหม และเปลี่ยนเป็นอะไร "รีเซ็ต" หมายความว่าอย่างไร
Sriram

ขอบคุณสำหรับเคล็ดลับ! ฉันมีปัญหาในการใช้สิ่งนี้สำหรับชื่อไฟล์ที่มีช่องว่างฝังอยู่ สำหรับคนอื่น ๆ ที่อาจใช้เป็นปัญหาที่ลองใส่evalที่ด้านหน้าของสายต่อที่นี้
cxw

2
สิ่งนี้ใช้ได้เมื่อคุณทราบตำแหน่งของพารามิเตอร์ที่คุณต้องการเปลี่ยนแปลง จะเกิดอะไรขึ้นถ้าคุณไม่รู้จริงและจำเป็นต้องเปลี่ยนแบบไดนามิก? ฉันลองใช้ $ set - "$ {: 1: $ pivot}" แต่ไม่ยอมรับตัวแปรที่นั่น
Daniele Segato

1
ฉันจะทำสิ่งเดียวกันจากภายในฟังก์ชันได้อย่างไร โซลูชันของคุณดูเหมือนจะไม่ทำงานเมื่อเรียกใช้จากภายในฟังก์ชัน
Hashken

3
คุณไม่สามารถเปลี่ยนพารามิเตอร์ตำแหน่งของสคริปต์จากภายในฟังก์ชันได้ - อาร์กิวเมนต์ของฟังก์ชันจะซ่อนไว้ อย่างไรก็ตามคุณสามารถจัดเก็บไว้ในอาร์เรย์และดำเนินการได้
thkala

23

การเพิ่มประสิทธิภาพเพื่อความชัดเจนและความสามารถในการบำรุงรักษาคุณอาจจะดีกว่าในการกำหนด$1และ$2ให้กับตัวแปรที่มีความหมายมากขึ้น (ฉันไม่รู้input_filename = $1และoutput_filename = $2หรือบางอย่าง) จากนั้นเขียนทับตัวแปรเหล่านั้น ( input_filename = 'chintz') โดยปล่อยให้อินพุตไปยังสคริปต์ไม่เปลี่ยนแปลงในกรณีที่เป็น ต้องการที่อื่น


ฉันต้องการแนวทางที่ฉันสามารถแก้ไขอาร์กิวเมนต์อินพุตได้เอง ฉันต้องทำเช่นนั้นเนื่องจากฉันต้องการคืนค่าจากสคริปต์ คำตอบที่แนะนำโดย thkala ใช้ได้ผลดี ขอบคุณสำหรับคำตอบ !!!
ศรีราม

3
@Johnsyweb เห็นด้วย เพื่อประโยชน์ในการอ่านของคุณเป็นวิธีที่ดีกว่า
Dss

1
"คุณจะดีกว่า" เสมอขึ้นอยู่กับกรณีการใช้งานซึ่งไม่มีให้
พระองค์

2
@Scott อายุมากกว่า 7 ปีและมีประสบการณ์มากกว่าตอนที่ฉันเขียนคำตอบนี้ฉันมีแนวโน้มที่จะเห็นด้วยกับคุณ
Johnsyweb

ตัวอย่างที่ใช้ไม่ได้ (นอกเหนือจากการใช้บางอย่างเช่น $ FIRST_PARAMETER): มีการใช้และความหมายของพารามิเตอร์ขึ้นอยู่กับค่าจริง
Igor Stoppa

0

ฉันรู้ว่านี่เป็นเรื่องเก่า แต่ฉันพบว่าคำตอบของthkalaมีประโยชน์มากดังนั้นฉันจึงใช้ความคิดและขยายความเล็กน้อยเพื่อให้ฉันสามารถเพิ่มค่าเริ่มต้นสำหรับอาร์กิวเมนต์ใด ๆ ที่ยังไม่ได้กำหนด - ตัวอย่างเช่น:


    # set defaults for the passed arguments (if any) if not defined.
    #
    arg1=${1:-"default-for-arg-1"}
    arg2=${2:-"default-for-arg-2"}
    set -- "${arg1}" "${arg2}"
    unset arg1 arg2

ฉันหวังว่านี่จะเป็นประโยชน์สำหรับคนอื่น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.