【问题标题】:Executing for-each in bash在 bash 中执行 for-each
【发布时间】:2009-11-08 19:55:11
【问题描述】:

我希望编写一个 Bash 单行程序,它为列表中的每个项目调用一次函数。例如,给定列表

foo bar baz
和程序“cowsay”,它会产生:
 _____
< foo >
 -----
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
 _____
< bar >
 -----
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
 _____
< baz >
 -----
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

(也许中间有额外的文字,并不重要)

我知道我可以使用 bash 脚本来做到这一点:

#!/bin/sh

for w in $@; do
  cowsay $w
done

但我无法想象没有其他方法可以做到这一点。

编辑:我想我最初的问题不是很清楚。我希望能够在不编写 bash 脚本的情况下做这样的事情:

locate foo | sed s/bar/baz/ | [other-processing] | [insert-magic-here] cowsay

关键是我试图避免编写脚本,这样我就可以将它添加到我的管道链中而无需考虑它。

【问题讨论】:

    标签: bash


    【解决方案1】:

    听起来你想使用 xargs。

    $ echo foo bar | xargs -n 1 cowsay
     _____
    < foo >
     -----
            \   ^__^
             \  (oo)\_______
                (__)\       )\/\
                    ||----w |
                    ||     ||
     _____
    < bar >
     -----
            \   ^__^
             \  (oo)\_______
                (__)\       )\/\
                    ||----w |
                    ||     ||
    

    【讨论】:

      【解决方案2】:

      你想要xargs。如果没有 forwhileuntil 循环结构,xargs 是唯一能满足您要求的东西。

      如果您需要 xargs 为每个输入执行命令,请使用 -n1,而不是将多个输入作为单独的参数执行。你的例子变成了:

      $ locate foo | sed s/bar/baz/ | [other-processing] | xargs -n1 cowsay
      

      【讨论】:

      • 啊哈!我知道 xargs,但不知道 -n 标志。太棒了,谢谢。
      【解决方案3】:

      一行:

      for i in foo bar baz; do cowsay $i; done
      

      或者更清楚:

      foobar="foo bar baz"
      
      for i in $foobar
      do
          cowsay $i
      done
      

      【讨论】:

      • 嗯,是的。但是有没有办法在没有 for 循环的情况下做到这一点?我想这才是真正的问题。
      【解决方案4】:

      正如其他人所说,xargs(1) 是您想要的,但它并不总是合适的。大多数情况下,当它对我来说失败时,就是我想运行一个 shell 函数的时候。 xargs 运行一个可执行命令。

      您可以在管道中放置一个循环,而无需将其放入 shell 脚本中:

      $ locate foo | sed s/bar/baz/ | [other-processing] | while read line ; do cowsay "$line" ; done
      

      如果 cowsay 是一个 shell 函数,则此管道可以工作,但不适用于 xargs。

      【讨论】:

      • 有趣。我不认为自己需要经常将它与 shell 函数一起使用,但很高兴知道这一点。希望它会防止一些头发拉扯和谷歌搜索。
      【解决方案5】:

      你可以写一个函数把它变成一个衬里:

      function foreach
      {
          func=$1; shift
          for arg in $@; do
              ${func} ${arg}
          done
      } 
      

      然后像这样调用它:

      foreach cosway foo bar baz
      

      【讨论】:

      • 这很接近,但仍然需要编写脚本。有没有内置的方法可以做到这一点?
      【解决方案6】:

      如果您对使用“for”循环不感兴趣,那么迭代字符串列表的其他选项是使用“while”或“until”循环。

      是不是你想写一个可以如下执行的bash脚本?

      $ cowsay-loop foo bar buzz

      【讨论】:

      • 对不起,我不清楚(再次)。这不是我要避免的 for 循环,而是脚本本身。我已经编辑了我的问题,希望更有意义。
      猜你喜欢
      • 1970-01-01
      • 2018-08-22
      • 2014-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-06
      • 1970-01-01
      相关资源
      最近更新 更多