bash loop ผ่านรายการของสตริง


15

เป็นไปได้หรือไม่ที่จะจัดรูปแบบตัวอย่างนี้:

for i in string1 string2 stringN
do
 echo $i
done

สิ่งที่คล้ายกับนี้:

for i in 
string1
string2
stringN
do
 echo $i
done

แก้ไข: ขออภัยในความสับสนไม่ทราบว่ามีวิธีการดำเนินการสคริปต์ที่แตกต่างกัน - sh <scriptname>เทียบกับbash <scriptname>และสิ่งที่ฉันไม่สามารถตั้งชื่อได้ตอนนี้ - #!/bin/shและ#!/bin/bash:)


ปัญหาที่คุณพยายามแก้ไขคืออะไร
jesse_b

คุณลองสิ่งที่คุณขอเพื่อดูว่ามันใช้งานได้หรือไม่
DopeGhoti

1
@Jesse_b ความสามารถในการอ่านและการจัดการความหลากหลายของสตริง

@DopeGhoti ใช่ฉันทำแล้ว

@ waayee: ในกรณีนี้อาร์เรย์คือทางออกที่ดีที่สุดของคุณ ดูคำตอบของ Glenn Jackman
jesse_b

คำตอบ:


35

การใช้อาร์เรย์ในทุบตีสามารถช่วยให้อ่านง่าย: ไวยากรณ์อาร์เรย์นี้ช่วยให้มีช่องว่างระหว่างคำ

strings=(
    string1
    string2
    "string with spaces"
    stringN
)
for i in "${strings[@]}"; do
    echo "$i"
done

1
ดูเหมือนว่าจะสวยงามที่สุด แต่น่าเสียดายที่ให้ข้อผิดพลาด: ข้อผิดพลาดทางไวยากรณ์: "(" ไม่คาดคิด

1
@ รอแล้วคุณไม่ได้ใช้มันใน Bash โปรดจำไว้ว่าshไม่จำเป็นต้องเป็น Bash และโดยเฉพาะอย่างยิ่งไม่ได้อยู่ใน Debian และ Ubuntu
ilkkachu

1
@ilkkachu คิดว่าฉันเข้าใจแล้ว - ต้องเรียกใช้ "bash <scriptname>" ไม่ใช่ "sh <scriptname>" :)

@ waayee หรือใส่ hashbang / shebang line ที่เหมาะสมแล้วเรียกใช้เหมือนปฏิบัติการ การอ่านที่ต้องการ: shebang พิจารณาเชลล์ที่รันสคริปต์หรือไม่
ilkkachu

1
@rrrrr อาจมีคำตอบสำหรับคำถามของคุณที่นี่: stackoverflow.com/q/12314451/7552
glenn jackman

4

คุณสามารถหลบหนีจาก linebreak ด้วยแบ็กสแลช:

$ for i in \
> hello \
> world
> do
> echo $i
> done
hello
world
$

3

คุณสามารถหลบเลี่ยงการขึ้นบรรทัดใหม่ก่อน / หลังแต่ละรายการที่คุณวนซ้ำ:

for i in \
    string1 \
    string2 \
    stringN
do
   printf '%s\n' "$i"
done

หรือสำหรับตัวอย่างง่ายๆนี้:

printf '%s\n' string1 string2 stringN

ซึ่งมีผลเหมือนกัน

ที่เกี่ยวข้อง:

การเปลี่ยนแปลงโดยใช้bashอาร์เรย์:

strings=(
    string1
    string2
    stringN
)

printf '%s\n' "${strings[@]}"


1
list='a b c d'
for element in $list;do 
    echo "$element"
done

คุณไม่มีเครื่องหมายอัฒภาค!
41754

โปรดทราบว่าสิ่งนี้จะทำงานได้ตราบใดที่แต่ละสตริงเป็นคำแยกต่างหาก ทันทีที่คุณมีช่องว่างในสายของคุณช่องว่างจะแบ่งสตริงออกเป็นหลายคำ นอกจากนี้หาก$listสตริงมีชื่อตัวละคร globbing ตัวอักษร ( list='* * * *') เปลือกอาจแทนที่ด้วยชื่อไฟล์ที่ตรงกัน
Kusalananda


0

ข้อความเดียวกันน้อยลง:

array=(
        string{1..7}
)

for i in "${array[@]}"; do
    echo "$i"
done

string1ฯลฯ ไม่แสดงค่าตามตัวอักษร แต่เป็นตัวยึดตำแหน่งดังนั้นวิธีนี้จึงใช้ไม่ได้
Stephen Kitt

ถ้าเป็นเช่นนั้นทำไมรบกวนarray ( … )? แค่ทำfor i in string{1..7}; do echo "$i"; done; คู่printf '%s\n' string{1..7}
αғsнιη
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.