【问题标题】:Simple Unix way of looping through space-delimited strings?循环通过空格分隔的字符串的简单Unix方式?
【发布时间】:2014-11-10 07:35:22
【问题描述】:

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

for every filename in file_list
    process(filename);
end

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

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

有更简单/更优雅的方法吗?

【问题讨论】:

  • 你试过for fname in $file_list吗?你用的是什么外壳?
  • @DaveNewton 不,我没有。那会奏效吗? (有点惊讶它是如此简单)我正在使用 bash。
  • @DaveNewton 它确实有效!非常感谢!被我的愚蠢震惊了..大声笑
  • for fname in $file_list 应该 not 工作:循环遍历 variable $file_name 内的名称。但是在您的问题中,您说它不是变量,而是文件名。

标签: bash unix sh


【解决方案1】:

xargs 也适用于一个不错的 1-liner。默认情况下,它会被任何空格分割。

xargs -n 1 process <file_list

或将文件名放在命令中:

# mac
xargs -n 1 -J % process(%) <file_list
# unix
xargs -n 1 -d " " -i process({}) <file_list

【讨论】:

    【解决方案2】:

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

    str="a b c d"
    
    for token in ${str}; do
        echo "$token"
    done
    

    【讨论】:

    • 对我不起作用。回声“a b c d”,而不是“a”“b”“c”“d”。使用 bash
    • @chaylan 你引用了 ${str} 吗?仅当 ${str} 未加引号时才会拆分。
    【解决方案3】:

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

    while read line
    do
       do things with $line
    done < file
    

    tr ' ' '\n' &lt; file 用新行替换空格,这样应该:

    while read line
    do
       do things with $line
    done < <(tr ' ' '\n' < file)
    

    测试

    $ 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
    

    【讨论】:

    • 不需要tr。请改用数组。由于您使用的是进程替换,因此可以安全地假设 shell 是 bash。 while IFS= read -ra filename; do printf "file -- %s\n" ${filename[@]}; done &lt; a
    【解决方案4】:

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

    for filename in `cat file_list`; do
      # Do stuff here
    done
    

    【讨论】:

    • 如果任何文件名可以包含空格或其他 shell 通配符,则不起作用。见mywiki.wooledge.org/DontReadLinesWithFor。虽然考虑到这里可能不可能的 OP。
    • @EtanReisner 没有一个文件名甚至可以包含空格,因为它们由空格分隔。另外,我怀疑你有一个名为 *. 的文件
    • 怀疑不是安全的适当替代品。例如,名称中带有[1] 的文件也会导致问题。是的,正如我编辑我的评论所说,在这种情况下,解决方案比其他解决方案更安全,因为主要问题实际上是预期的行为,但其余的仍然是可能的。
    • @EtanReisner 是的,所以这绝对不是一个应该以 root 权限或通过网络运行的程序。虽然它确实提供了 shell globing 作为一个特性。
    • 如果是bash,使用内置的for filename in $(&lt; file_list)
    猜你喜欢
    • 2012-01-30
    • 1970-01-01
    • 2012-04-19
    • 2021-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-08
    • 2010-12-01
    相关资源
    最近更新 更多