ในสคริปต์ bash shell ให้เขียน a for loop ที่วนซ้ำค่าสตริง


24

ใน bash ฉันรู้ว่ามันเป็นไปได้ที่จะเขียนforloop ซึ่งตัวแปรควบคุมการiวนซ้ำนั้นวนซ้ำตามจำนวนเต็มที่ระบุ ตัวอย่างเช่นฉันสามารถเขียน bash shell script ที่พิมพ์จำนวนเต็มระหว่าง 1 ถึง 10:

#!/bin/bash

for i in {1..10}
do
 echo $i
done

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

#!/bin/bash

for fname in {"a.txt", "b.txt", "c.txt"}
do
 echo $fname
done

กล่าวอีกนัยหนึ่งในการทำซ้ำครั้งแรกfnameควรมีค่าfname="a.txt"ในขณะที่การทำซ้ำครั้งที่สองfnameควรมีค่าfname="b.txt"และอื่น ๆ น่าเสียดายที่ดูเหมือนว่าไวยากรณ์ข้างต้นไม่ถูกต้องนัก ฉันต้องการได้รับผลลัพธ์:

a.txt

b.txt

c.txt

แต่เมื่อฉันลองรหัสข้างต้นฉันได้ผลลัพธ์นี้:

{a.txt,

b.txt,

c.txt}

คุณช่วยฉันในการกำหนดไวยากรณ์ที่ถูกต้องเพื่อที่ฉันจะสามารถเปลี่ยนค่า / เนื้อหาของตัวแปรได้fnameหรือไม่? ขอขอบคุณสำหรับเวลาของคุณ.


5
เอาออก{}คุณไม่ต้องการอะไรที่จะวนซ้ำรายการ (เว้นวรรค)
Mat

3
@Mat วิธีลบ{} และ, s ทางเลือกคือการลบช่องว่าง ดังนั้นทั้งหรือ"a.txt" "b.txt" "c.txt" {"a.txt","b.txt","c.txt"}แต่ฉันชอบ{a..c}.txtแทน
จัดการ

คำตอบ:


39

ไวยากรณ์ที่ถูกต้องมีดังนี้:

#!/bin/bash

for fname in a.txt b.txt c.txt
do
  echo $fname
done

9
นอกจากนี้สมมติว่าอาร์เรย์ของชื่อคุณสามารถใช้ไวยากรณ์fnames=( a.txt b.txt c.txt ) for f in ${fnames[@]}; do echo $f; done

1
เป็นความจริงfor fname in a.txt b.txt c.txtและfor fname in "a.txt" "b.txt" "c.txt"ให้ผลลัพธ์ที่เหมือนกันหรือไม่
Andrew

แอนดรูใช่มันเป็นเรื่องจริง พวกเขาจะให้ผลลัพธ์ที่เหมือนกัน
Ali Gangji

1
แน่นอนคุณควรใช้for f in "${fnames[@]}"; do echo $f; done(มีเครื่องหมายคำพูดล้อมรอบ${fnames[@]}) หากfnamesค่าอาจมีช่องว่าง และคุณควรใช้"$f"โดยเฉพาะอย่างยิ่งถ้าคุณทำอะไรที่ซับซ้อนกว่าecho(เช่นcatหรือcp) (และแม้ว่าคุณจะทำเพียงแค่echoคุณควรใช้printfแทน)
สกอตต์

ฉันคิดว่า @ user13742 ควรสังเกตด้วยในคำตอบ
Fallenreaper

1

ดูเหมือนว่าฉันคุณควรจะทำ ...

printf %s.txt\\n a b c

ฉันชอบสิ่งนี้แม้ว่า OP น่าจะมีบางอย่างในใจที่จะทำนอกเหนือจากเสียงสะท้อนก่อนที่เขาจะทำ
Elder Geek

0

ตามที่ระบุไว้โดย user13742 ในความคิดเห็นเราสามารถใช้ประโยชน์จากอาร์เรย์ในbashและksh:

#!/usr/bin/env bash

files_list=( "a.txt" "b.txt" "c and space.txt" )

for i in "${files_list[@]}"
do
    echo "$i"
    # do something else here,maybe
done

และทำงานเป็นเช่นนั้น:

$ ./iterate_files_array.sh                                                      
a.txt
b.txt
c and space.txt

อย่างไรก็ตามเชลล์บางตัวเช่นdash( /bin/shบน Ubuntu) ไม่รองรับอาร์เรย์ ในกรณีเช่นนี้เราสามารถใช้โครงสร้างเอกสารที่นี่:<<

#!/bin/sh

while IFS= read -r line
do
    echo "$line"
done << EOL
one.txt
two.txt
with space.txt
EOL
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.