ฉันจะใช้ $ * ขณะที่ละเว้นตัวแปรอินพุตบางอย่างเช่น $ 1 และ $ 2 ในสคริปต์ทุบตีได้อย่างไร


15

ตัวอย่างเช่น,

elif [[ $append = $1 ]]
then
  touch ~/directory/"$2".txt
  echo "$variable_in_question" >> ~/directory/"$2".txt

หากต้องการสร้างไฟล์ข้อความที่มีการป้อนข้อมูลต่อไปนี้ทั้งหมด"$2"หรือต่อท้ายไฟล์ข้อความที่มีอยู่พร้อมกับการป้อนข้อมูลทั้งหมดต่อไปนี้"$2"ฉันจะใช้อะไรแทน"$variable_in_question"บรรทัดที่ 4

ฉันเป็นพื้นต้องการ"$*"แต่ถนัดและ"$1""$2"

คำตอบ:


32

คุณสามารถใช้bashการขยายพารามิเตอร์เพื่อระบุช่วงซึ่งใช้ได้กับพารามิเตอร์ตำแหน่งเช่นกัน สำหรับ$3... $nมันจะเป็น:

"${@:3}" # expands to "$3" "$4" "$5" …
"${*:3}" # expands to "$3 $4 $5 …"

โปรดทราบว่าทั้งสอง$@และละเว้นอาร์กิวเมนต์แรก$* $0หากคุณสงสัยว่าหนึ่งที่จะใช้ในกรณีของคุณ: มันมาก$@น่าจะเป็นที่คุณต้องการที่ยกมา อย่าใช้$*เว้นแต่คุณจะไม่ต้องการให้มีการเสนอราคาแบบแยกอาร์กิวเมนต์

คุณสามารถลองได้ดังนี้:

$ bash -c 'echo "${@:3}"' 0 1 2 3 4 5 6
3 4 5 6
$ echo 'echo "${@:3}"' >script_file
$ bash script_file 0 1 2 3 4 5 6
2 3 4 5 6

โปรดทราบว่าในตัวอย่างแรก$0จะเต็มไปด้วยอาร์กิวเมนต์แรก0ในขณะที่เมื่อใช้ในสคริปต์$0จะเต็มไปด้วยชื่อของสคริปต์แทนตามตัวอย่างที่สองแสดงให้เห็น bashแน่นอนว่าชื่อของสคริปต์นั้นเป็นอาร์กิวเมนต์แรกซึ่งปกติแล้วมันจะไม่ถูกมองว่าเป็นเช่นนั้น - เหมือนกันสำหรับสคริปต์ที่ทำให้สามารถเรียกใช้งานได้และเรียกว่า“ โดยตรง” ดังนั้นในตัวอย่างแรกเรามี$0= 0, $1= 1ฯลฯ ในขณะที่ในวินาทีมันคือ$0= script_file, $1= 0, $2= 1ฯลฯ เลือกอาร์กิวเมนต์ทุกที่เริ่มต้นด้วย${@:3}$3

ตัวอย่างเพิ่มเติมสำหรับช่วงที่เป็นไปได้:

 # two arguments starting with the third
$ bash -c 'echo "${@:3:2}"' 0 1 2 3 4 5 6
3 4
 # every argument starting with the second to last one
 # a negative value needs either a preceding space or parentheses
$ bash -c 'echo "${@: -2}"' 0 1 2 3 4 5 6
5 6
 # two arguments starting with the fifth to last one
$ bash -c 'echo "${@:(-5):2}"' 0 1 2 3 4 5 6
2 3

อ่านเพิ่มเติม:


27

คุณสามารถใช้shiftbuiltin:

$ help shift
shift: shift [n]
    Shift positional parameters.

    Rename the positional parameters $N+1,$N+2 ... to $1,$2 ...  If N is
    not given, it is assumed to be 1.

    Exit Status:
    Returns success unless N is negative or greater than $#.

อดีต รับ

$ cat argtest.bash 
#!/bin/bash

shift 2

echo "$*"

แล้วก็

$ ./argtest.bash foo bar baz bam boo
baz bam boo

3
@Oreoplasm ฉันคิดว่าเป็นมูลค่าการกล่าวขวัญว่าshiftวิธีการที่จะทำให้มันเป็นไปไม่ได้ที่จะเข้าถึง$1และ$2หลังจากที่คุณเปลี่ยนพวกเขา ในสคริปต์ของคุณคุณใช้$2ควบคู่ไปกับ$variable_in_questionคุณต้องเปลี่ยนหรือใช้วิธีการขยายพารามิเตอร์
ของหวาน

6
shiftเป็นสิ่งที่ดีเมื่อคนแรกหรือ args มากขึ้นเป็นพิเศษและมันทำให้ความรู้สึกที่จะเลือกพวกเขาออกไปในตัวแปรแยกต่างหาก ( foo="$1"; bar="$2";หรือif [[ something with $1 ]];then blah blah; shift. แต่ @ คำตอบขนมด้วยวิธีที่ไม่ทำลายเป็นสิ่งที่ดีในกรณีอื่น ๆ เมื่อคุณจะยังคงต้องการรายการเต็มรูปแบบในภายหลัง หรือเมื่อคุณใช้ไวยากรณ์ที่ชื่นชอบมากขึ้นในการเลือก args ที่ จำกัด ไม่ จำกัด อินฟินิตี้โดยไม่แนะนำ args ที่ว่างเปล่าให้กับคำสั่งหาก$@ไม่มีองค์ประกอบมากมาย
Peter Cordes

13

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

ตัวอย่างเช่นถ้าฉันต้องการ args ทั้งหมดยกเว้นอันที่หนึ่งที่สี่และห้า:

args=( "$@" )
unset args[0] args[3] args[4]
echo "${args[@]}"

ในการคัดลอกดัชนีจะขยับขึ้น 1 เนื่องจากไม่ได้เป็นส่วนหนึ่งของ$0$@


1
แน่นอนว่าเป็นไปได้ที่จะรวมเช่นecho "${args[@]:2}"สำหรับอาร์กิวเมนต์ที่สามถึงอาร์กิวเมนต์สุดท้าย
ของหวาน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.