简单的Unix循环空格分隔字符串的方式?

Sib*_*ing 16 unix bash sh

我有一个名为的文件,file_list包含以空格分隔的字符串,每个字符串都是要处理的文件的文件名.我现在希望遍历所有文件名并逐个处理它们.伪代码是

for every filename in file_list
    process(filename);
end
Run Code Online (Sandbox Code Playgroud)

我想出了一个相当笨拙的解决方案,就是这样

  1. 通过将文件加载到变量中 filenames='cat file_list'
  2. 计算空格数N,tr -cd ' ' <temp_list | wc -c
  3. 从1循环到N空格并用空格解析每个文件名cut

这样做有更简单/更优雅的方式吗?

ran*_*ame 19

最简单的方法是在bourne shell中使用一段时间的经典技巧.

for filename in `cat file_list`; do
  # Do stuff here
done
Run Code Online (Sandbox Code Playgroud)

  • 如果任何文件名可以包含空格或其他 shell 通配符,则不起作用。请参阅 http://mywiki.wooledge.org/DontReadLinesWithFor 。尽管考虑到在这里可能无法实现的 OP。 (2认同)
  • 怀疑不是安全的正确替代品.例如,名称中带有"[1]"的文件也会导致问题.是的,正如我编辑我的评论,在这种情况下说解决方案比其他解决方案更安全,因为主要问题实际上是预期的行为,但其余的仍然是可能的. (2认同)
  • 如果是bash,请在$(<file_list)`中使用builtin`for filename (2认同)

fed*_*qui 7

您可以更改文件,使单词以行分隔而不是空格分隔.这样,您可以使用典型的语法:

while read line
do
   do things with $line
done < file
Run Code Online (Sandbox Code Playgroud)

随着tr ' ' '\n' < file你用新行替换空格,所以这应该:

while read line
do
   do things with $line
done < <(tr ' ' '\n' < file)
Run Code Online (Sandbox Code Playgroud)

测试

$ cat a
hello this is a set of strings
$ while read line; do echo "line --> $line"; done < <(tr ' ' '\n' < a)
line --> hello
line --> this
line --> is
line --> a
line --> set
line --> of
line --> strings
Run Code Online (Sandbox Code Playgroud)


小智 6

这是没有人发布的另一种方法:

str="a b c d"

for token in ${str}; do
    echo "$token"
done
Run Code Online (Sandbox Code Playgroud)

  • 我采用了这种方法,但不得不加入 echo,例如 `for token in $(echo ${str}); 做` (7认同)
  • 对我不起作用。回显“abc d”,而不是“a”“b”“c”“d”。使用bash (5认同)
  • @chaylan 你引用了 ${str} 吗?仅当 ${str} 未加引号时才会拆分。 (4认同)
  • 这在“bash”中有效,但在“zsh”中无效,这可能解释了为什么有些人发现它有效而其他人则不然。 (3认同)