Trong tập lệnh bash shell, viết một vòng lặp for lặp lại trên các giá trị chuỗi


24

Trong bash, tôi biết rằng có thể viết một forvòng lặp trong đó một số biến điều khiển vòng ilặp lặp qua các số nguyên được chỉ định. Ví dụ: tôi có thể viết tập lệnh bash shell in các số nguyên trong khoảng từ 1 đến 10:

#!/bin/bash

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

Thay vào đó có thể lặp lại một biến điều khiển vòng lặp là một chuỗi không, nếu tôi cung cấp một danh sách các chuỗi? Ví dụ: giả sử tôi có một chuỗi fnameđại diện cho tên tệp. Tôi muốn gọi một nhóm lệnh cho mỗi tên tệp. Ví dụ: tôi có thể muốn in nội dung fnamesử dụng lệnh như thế này:

#!/bin/bash

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

Nói cách khác, ở lần lặp thứ nhất, fnamenên có giá trị fname="a.txt", trong khi ở lần lặp thứ hai, fnamenên có giá trị fname="b.txt", v.v. Thật không may, có vẻ như cú pháp trên không hoàn toàn chính xác. Tôi muốn có được đầu ra:

a.txt

b.txt

c.txt

nhưng khi tôi thử đoạn mã trên, tôi nhận được kết quả đầu ra này:

{a.txt,

b.txt,

c.txt}

Bạn có thể vui lòng giúp tôi xác định cú pháp chính xác để tôi có thể thay đổi giá trị / nội dung của biến fnamekhông? Cảm ơn bạn đã dành thời gian.


5
Xóa {}, bạn không cần bất cứ điều gì để lặp qua danh sách (được phân cách bằng dấu cách)
Mat

3
@Mat phương tiện loại bỏ {} các ,s. Thay thế là để loại bỏ các không gian. Vì vậy, "a.txt" "b.txt" "c.txt"hoặc {"a.txt","b.txt","c.txt"}. Nhưng tôi thích {a..c}.txtthay thế.
manatwork

Câu trả lời:


39

Cú pháp đúng như sau:

#!/bin/bash

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

9
Ngoài ra, giả sử một mảng tên fnames=( a.txt b.txt c.txt )bạn có thể sử dụng cú pháp for f in ${fnames[@]}; do echo $f; done.

1
Có đúng như vậy for fname in a.txt b.txt c.txtfor fname in "a.txt" "b.txt" "c.txt"mang lại kết quả giống hệt nhau?
Andrew

Andrew, đúng vậy. Họ sẽ mang lại kết quả giống hệt nhau
Ali Gangji

1
Tất nhiên bạn nên sử dụng for f in "${fnames[@]}"; do echo $f; done(có dấu ngoặc kép xung quanh ${fnames[@]}) nếu các fnamesgiá trị có thể chứa khoảng trắng. Và bạn nên sử dụng "$f", đặc biệt nếu bạn đang làm bất cứ điều gì phức tạp hơn echo(ví dụ: cathoặc cp). (Và ngay cả khi bạn chỉ làm echo, bạn nên sử dụng printfthay thế.)
Scott

Tôi nghĩ @ user13742 cũng nên được ghi chú trong câu trả lời.
Fallenreaper

1

Dường như với tôi bạn chỉ nên làm ...

printf %s.txt\\n a b c

Tôi thích điều này mặc dù OP có thể có ý định làm gì đó ngoài tiếng vang trước khi anh ta hoàn thành.
Anh Cả Geek

0

Theo ghi nhận của user13742 trong các bình luận , chúng ta có thể sử dụng các mảng trong bashksh:

#!/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

Và hoạt động như vậy:

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

Tuy nhiên, một số shell như dash( /bin/shtrên Ubuntu) không hỗ trợ mảng. Trong trường hợp như vậy, chúng ta có thể sử dụng cấu trúc tài liệu ở đây:<<

#!/bin/sh

while IFS= read -r line
do
    echo "$line"
done << EOL
one.txt
two.txt
with space.txt
EOL
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.