เป็นไปได้ไหมที่จะใช้ตัวแปรพารามิเตอร์เชลล์ ($ 1, …, $ @) โดยตรงใน CLI


9

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

ฉันพยายามที่จะแก้ปัญหาโดยใช้ตัวอย่างง่ายๆด้วยวิธีต่อไปนี้:

(find $1) /tmp
sh -c '(find $1) /tmp'
sh -c "find $1" /tmp
echo '(find $1) /tmp' | sh

และด้วยชุดค่าผสมอื่น ๆ ทดลองโดยการเพิ่มคำสั่งล่าม shebang #!/bin/sh -xแต่ไม่ได้ผลลัพธ์ที่ต้องการ

ฉันสามารถทำสิ่งนี้ได้ง่ายๆ


1
(find $1) /tmpเป็นข้อผิดพลาดทางไวยากรณ์ ที่จริงแล้ว(any-command) more-argumentsเป็นข้อผิดพลาดทางไวยากรณ์ คุณช่วยอธิบายสิ่งที่คุณพยายามทำแตกต่างกันได้ไหม
Celada

2
@Celada ก็ไม่ได้เป็นไวยากรณ์ผิดพลาดในเปลือกหอยของrcครอบครัว ( rc, es, akanga... ) find $1 /tmpซึ่งในกรณีที่ว่าที่เทียบเท่ากับ
Stéphane Chazelas

คำตอบ:


15

อาร์กิวเมนต์แรกหลังจากsh -c inline-scriptไป$0(ซึ่งยังใช้สำหรับข้อความผิดพลาด) และส่วนที่เหลือจะไปใน$1, $2...

$ sh -c 'blah; echo "$0"; echo "$1"' my-inline-script arg
my-inline-script: blah: command not found
my-inline-script
arg

ดังนั้นคุณต้องการ:

sh -c 'find "$1"' sh /tmp

(ในสมัยก่อนคุณสามารถค้นหาshการใช้งานที่หาเรื่องแรกเข้าไป$1แทนดังนั้นคุณจะทำ:

sh -c 'find "$1"' /tmp /tmp

หรือ:

sh -c 'shift "$2"; find "$@"' sh 3 2 /tmp1 /tmp2

เพื่อพิจารณาพฤติกรรมทั้งสอง แต่เชลล์เหล่านั้นหายไปแล้วในขณะนี้ที่ POSIX แพร่หลายและมีอยู่ทั่วไป)


หากคุณต้องการชุด$1, $2ในขอบเขตท้องถิ่นภายในเปลือกปัจจุบันที่ที่คุณต้องการใช้ฟังก์ชั่น ในกระสุนคล้ายบอร์น:

my_func() {
  find "$1"
}
my_func /tmp

เชลล์บางตัวรองรับฟังก์ชั่นนิรนาม นั่นคือกรณีของzsh:

(){find "$1"} /tmp

หรือes:

@{find $1} /tmp

หากต้องการเปลี่ยนพารามิเตอร์ตำแหน่งปัจจุบันอย่างถาวรไวยากรณ์จะขึ้นอยู่กับเชลล์ dchirikov ได้ครอบคลุมแล้วบอร์นเหมือนเปลือกหอย (บอร์น, Korn, bash, zsh, POSIX, ash, yash... )

ไวยากรณ์คือ:

set arg1 arg2 ... argn

อย่างไรก็ตามคุณต้องการ:

set --

หากต้องการล้างรายการ (หรือshift "$#") และ

set -- -foo

เพื่อตั้งค่า$1เป็นสิ่งที่เริ่มต้นด้วย-หรือ+ดังนั้นจึงเป็นนิสัยที่ดีที่จะใช้set --โดยเฉพาะอย่างยิ่งเมื่อใช้ข้อมูลโดยพลการเช่นset -- "$@" other-argการเพิ่มอาร์กิวเมนต์ไปยังจุดสิ้นสุดของรายการพารามิเตอร์ตำแหน่ง

ในเชลล์ของcshตระกูล ( csh, tcsh) คุณกำหนดให้กับargvอาร์เรย์:

set argv=(arg1 arg2)

ในเปลือกหอยของrcครอบครัว ( rc, es, akanga) เพื่อ*อาร์เรย์:

*=(arg1 arg2)

แม้ว่าคุณสามารถกำหนดองค์ประกอบเป็นรายบุคคล:

2=arg2

ในfishการพารามิเตอร์ตำแหน่งอยู่ในargvอาร์เรย์เท่านั้น (ไม่$1, $@มี):

set argv arg1 arg2

ในzshการเข้ากันได้กับcshคุณยังสามารถกำหนดให้กับargvอาร์เรย์:

argv=(arg1 arg2)
argv[4]=arg4

และคุณยังสามารถ:

5=arg5

นั่นหมายความว่าคุณสามารถทำสิ่งต่าง ๆ เช่น:

argv+=(another-arg)

เพื่อเพิ่มการโต้แย้งไปยังจุดสิ้นสุดและ:

argv[-1]=()
argv[2]=()

เพื่อลบอาร์กิวเมนต์จากปลายหรือตรงกลางซึ่งคุณไม่สามารถทำกับเชลล์อื่น ๆ ได้อย่างง่ายดาย


7
set --

คือสิ่งที่คุณต้องการ:

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