เพิ่มองค์ประกอบใหม่ให้กับอาร์เรย์โดยไม่ต้องระบุดัชนีใน Bash


คำตอบ:


1540

ใช่นั่นคือ:

ARRAY=()
ARRAY+=('foo')
ARRAY+=('bar')

คู่มืออ้างอิง Bash :

ในบริบทที่คำสั่งการมอบหมายกำลังกำหนดค่าให้กับตัวแปรเชลล์หรือดัชนีอาเรย์ (ดูที่อาร์เรย์) สามารถใช้ตัวดำเนินการ '+ =' เพื่อผนวกหรือเพิ่มค่าก่อนหน้าของตัวแปร


21
ใช้งานได้ดีกับ bash 3.2.48 (OS X 10.8.2) โปรดทราบว่าARRAYเป็นเพียงตัวยึดตำแหน่งสำหรับชื่อตัวแปรจริง แม้ว่าดัชนีอาเรย์ของคุณจะไม่เรียงลำดับ แต่การผนวกด้วย+=ก็จะกำหนดให้กับดัชนีสูงสุด + 1
mklement0

3
มีบางอย่างเช่นนี้ใน bash เวอร์ชั่น 4.2.24 (1) หรือไม่?
Ali Ismayilov

195
สิ่งสำคัญคือให้สังเกตว่า ARRAY + = ('foo') นั้นแตกต่างจาก ARRAY + = 'foo' ซึ่งจะผนวกสตริง 'foo' เข้ากับรายการด้วยคีย์ที่ต่ำที่สุด (?)
TheConstructor

8
ตามwiki.bash-hackers.org/scripting/bashchangesไวยากรณ์นี้ปรากฏขึ้นครั้งแรกในเวอร์ชัน 3.1-alpha1
David Yaw

39
@Jas: ในการเข้าถึงอาร์เรย์ทั้งหมดคุณต้องใช้${myarray[@]}- การอ้างอิงตัวแปรอาร์เรย์ราวกับว่ามันเป็นสเกลาร์นั้นเหมือนกับการเข้าถึงองค์ประกอบ 0 ในคำอื่น ๆ : เป็นเช่นเดียวกับ$myarray ${myarray[0]}
mklement0

76

ดังที่Dumb Guyชี้ให้เห็นสิ่งสำคัญคือต้องทราบว่าอาร์เรย์เริ่มต้นที่ศูนย์และเรียงตามลำดับหรือไม่ เนื่องจากคุณสามารถกำหนดและยกเลิกการตั้งค่าดัชนีที่${#array[@]}ไม่ต่อเนื่องกันได้จึงไม่ใช่รายการถัดไปในตอนท้ายของอาร์เรย์

$ array=(a b c d e f g h)
$ array[42]="i"
$ unset array[2]
$ unset array[3]
$ declare -p array     # dump the array so we can see what it contains
declare -a array='([0]="a" [1]="b" [4]="e" [5]="f" [6]="g" [7]="h" [42]="i")'
$ echo ${#array[@]}
7
$ echo ${array[${#array[@]}]}
h

นี่คือวิธีรับดัชนีล่าสุด:

$ end=(${!array[@]})   # put all the indices in an array
$ end=${end[@]: -1}    # get the last one
$ echo $end
42

นั่นแสดงให้เห็นถึงวิธีการรับองค์ประกอบสุดท้ายของอาร์เรย์ คุณมักจะเห็นสิ่งนี้:

$ echo ${array[${#array[@]} - 1]}
g

อย่างที่คุณเห็นเพราะเรากำลังยุ่งกับอาร์เรย์กระจัดกระจายนี่ไม่ใช่องค์ประกอบสุดท้าย วิธีนี้ใช้ได้ทั้งในเบาบางและต่อเนื่องกันแม้ว่า:

$ echo ${array[@]: -1}
i

3
สิ่งที่ยอดเยี่ยม; ไม่เคยรู้ว่าไวยากรณ์การแยกสตริงย่อยสามารถนำไปใช้กับอาร์เรย์ได้เช่นกัน กฎที่กำหนดโดยการลองผิดลองถูกคือ (bash 3.2.48): ${array[@]: start[:count]}ส่งคืนการนับ elems หรือหากไม่ได้ระบุทั้งหมดที่เหลือ elems เริ่มต้นที่องค์ประกอบต่อไปนี้: - หากเริ่มต้น> = 0: จากองค์ประกอบอื่น ดัชนีของใครคือ> = เริ่ม - ถ้าเริ่ม <0: จาก elem ซึ่งมีดัชนีคือ (ดัชนีอาร์เรย์สุดท้าย + 1) - abs (เริ่มต้น); ถ้ำ: ถ้า abs (start)> (ดัชนีอาร์เรย์สุดท้าย + 1) สตริงว่างจะถูกส่งคืน หากมีการระบุการนับองค์ประกอบจะถูกส่งคืนแม้ว่าดัชนีของพวกเขาจะไม่ต่อเนื่องกันตั้งแต่เริ่มต้น
mklement0

3
@mklement: ใน Bash 4.2 คุณสามารถใช้ตัวห้อยอาร์เรย์เชิงลบเพื่อเข้าถึงองค์ประกอบที่นับจากจุดสิ้นสุดของอาร์เรย์ ${array[-1]}
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

ขอบคุณมากที่รู้ OS X (จนถึง 10.8.2) ยังคงใช้ 3.2.48 และstackoverflow.com/questions/10418616//บอกฉันว่าน่าเสียดายที่ "Apple ใช้ Bash เวอร์ชันเก่าเพราะพวกเขาไม่ได้จัดส่งรหัสที่ได้รับอนุญาต ภายใต้ GPL3 "
mklement0

49
$ declare -a arr
$ arr=("a")
$ arr=("${arr[@]}" "new")
$ echo ${arr[@]}
a new
$ arr=("${arr[@]}" "newest")
$ echo ${arr[@]}
a new newest

8
ดีสำหรับรุ่นทุบตีที่ไม่รองรับซีแมนทิกส์ของ + = ตัวดำเนินการที่อธิบายโดย e-t172
akostadinov

12
โซลูชันที่เข้ากันได้แบบย้อนหลังที่ดี แต่ระวังว่าหากองค์ประกอบใด ๆ ที่มีอยู่มีช่องว่างอยู่ในนั้นองค์ประกอบเหล่านั้นจะถูกแบ่งออกเป็นหลายองค์ประกอบ ใช้arr=("${arr[@]}" "new")ถ้าคุณมีองค์ประกอบที่มีช่องว่างในนั้น
kbolino

1
สิ่งนี้สามารถใช้เพื่อผลักดันด้านหน้าของอาร์เรย์ซึ่งเป็นสิ่งที่ฉันต้องการ
Tomáš Zato - Reinstate Monica

29

หากอาร์เรย์ของคุณเรียงตามลำดับเสมอและเริ่มต้นที่ 0 คุณสามารถทำได้ดังนี้:

array[${#array[@]}]='foo'

# gets the length of the array
${#array_name[@]}

หากคุณใช้ช่องว่างระหว่างเครื่องหมายเท่ากับ:

array[${#array[@]}] = 'foo'

จากนั้นคุณจะได้รับข้อผิดพลาดคล้ายกับ:

array_name[3]: command not found

5
ใช่คุณทำได้ แต่+=ไวยากรณ์ (ดูคำตอบของ @ e-t172) คือ (a) ง่ายขึ้นและ (b) ยังทำงานกับอาร์เรย์ที่ไม่ต่อเนื่องกันและ / หรือไม่เริ่มต้นด้วย 0
mklement0

จริง ๆ แล้ววิธีแก้ปัญหานี้ (สำหรับฉัน) ทำงานได้ดีกว่า "+ =" เพราะในระยะหลังบางครั้งความยาวก็ไม่ถูกต้อง (เพิ่มขึ้นสองเมื่อเพิ่มองค์ประกอบหนึ่ง) ... ดังนั้นฉันชอบคำตอบนี้! :)
Pierpaolo Cira

วิธีนี้ใช้ได้กับ bash รุ่นก่อนหน้า+=อีกด้วยเช่นเพิ่มก่อนเช่นรุ่นที่ 2
Zoey Hewll

1
นอกจากนี้ยังใช้งานได้เมื่อองค์ประกอบของคุณมีช่องว่างในพวกเขา - $arr += ($el)ดูเหมือนจะแบ่งสตริงโดยช่องว่างและเพิ่มแต่ละองค์ประกอบ
สูงสุด

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