在bash shell脚本中,编写对字符串值进行迭代的for循环


24

在bash中,我知道可以编写一个for循环,其中一些循环控制变量i在指定的整数上进行迭代。例如,我可以编写一个bash shell脚本来打印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 Mat 2012年

3
@Mat装置取出{} 所述,第 另一种方法是删除空格。因此,无论"a.txt" "b.txt" "c.txt"{"a.txt","b.txt","c.txt"}。但是我更喜欢{a..c}.txt
manatwork 2012年

Answers:


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 2012年

1
当然for f in "${fnames[@]}"; do echo $f; done${fnames[@]}如果fnames值可能包含空格,则应使用(带有引号)。而且您应该使用"$f",尤其是当您做的事情比echo(例如catcp)复杂得多时。(即使您只是在做echo,也应该printf改用。)
Scott

我认为@ user13742也应在答案中注明。
Fallenreaper

1

在我看来您应该这样做...

printf %s.txt\\n a b c

我喜欢这样做,尽管OP可能在做之前除了回声之外还想做些其他事情。
年长者怪胎

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

但是,某些shell(例如dash/bin/sh在Ubuntu上)不支持数组。在这种情况下,我们可以使用here-document结构:<<

#!/bin/sh

while IFS= read -r line
do
    echo "$line"
done << EOL
one.txt
two.txt
with space.txt
EOL
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.