如何将shell命令应用于命令输出的每一行?


192

假设我从命令(例如ls -1)获得了一些输出:

a
b
c
d
e
...

我想echo依次对每个命令应用一个命令(例如)。例如

echo a
echo b
echo c
echo d
echo e
...

在bash中最简单的方法是什么?


3
ls -1可能是这里的一个例子,但重要的是要记住,解析输出不好ls。参见:mywiki.wooledge.org/ParsingLs
codeforester

Answers:


217

这可能是最容易使用的xargs。在您的情况下:

ls -1 | xargs -L1 echo

-L标志确保正确读取输入。从手册页xargs

-L number
    Call utility for every number non-empty lines read. 
    A line ending with a space continues to the next non-empty line. [...]

24
ls自动-1在管道中进行。
暂停,直到另行通知。

5
@Dennis,看起来不像:ls | xargs -L2 echols -1 | xargs -L2 echo给出两个不同的输出。前者全都在一条线上。
Alex Budovski

2
@Alex:我得到相同的输出。
暂停,直到另行通知。

6
xargs只能运行可执行文件,而不能运行Shell函数或Shell内置命令。对于前者,最好的解决方案可能是一个read循环的解决方案。
pabouk

12
我希望这个答案能解释-L1其用途。
Wyck

163

您可以在每行上使用基本的前置操作:

ls -1 | while read line ; do echo $line ; done

或者,您可以将输出通过管道传递给sed以进行更复杂的操作:

ls -1 | sed 's/^\(.*\)$/echo \1/'

1
sed命令似乎不起作用:似乎sh: cho: not found a sh: cho: not foundein echo作为sed命令之类。
Alex Budovski

+1为while循环。cmd1 | while read line; do cmd2 $line; done。还是while read line; do cmd2 $line; done < <(cmd1)不创建子shell。这是sed命令的简化版本:sed 's/.*/echo &/'
已暂停,直至另行通知。

1
@Alex:将双引号更改为单引号。
暂停,直到另行通知。

5
"$line"在while循环中加引号,以避免单词分裂。
ignis

3
尝试使用read -r line以防止read被转义字符弄乱。例如echo '"a \"nested\" quote"' | while read line; do echo "$line"; doneGives "a "nested" quote",它已经逃脱了。如果我们做到了,echo '"a \"nested\" quote"' | while read -r line; do echo "$line"; done我们将"a \"nested\" quote"如期实现。参见wiki.bash-hackers.org/commands/builtin/read
Warbo,2015年

9

您可以使用for循环

用于*中的文件; 做
   回声“ $文件”
做完了

请注意,如果所讨论的命令接受多个参数,则使用xargs几乎总是更有效,因为它只需生成一次所讨论的实用程序即可,而不必多次生成。


1
值得描述xargs的正确/安全使用,即。printf '%s\0' * | xargs -0 ...-否则,它是用空格,报价等文件名非常不安全
查尔斯·达菲

8

只要是GNU sed,您实际上就可以使用sed来做。

... | sed 's/match/command \0/e'

这个怎么运作:

  1. 用命令匹配替换匹配
  2. 替代时执行命令
  3. 用命令输出替换替换的行。

太棒了 我忘了把 e命令放在末尾,但是在看到您的答复后才这样做,并且它起作用了。当SED匹配一行时,我试图在1000和15000之间附加一个随机ID。 cat /logs/lfa/Modified.trace.log.20150904.pw | sed -r 's/^(.*)(\|006\|00032\|)(.*)$/echo "\1\2\3 - ID `shuf -i 999-14999 -n 1`"/e'
sgsi 2015年


2

xargs失败,并带有反斜杠,引号。它必须像

ls -1 |tr \\n \\0 |xargs -0 -iTHIS echo "THIS is a file."

xargs -0选项:

-0, --null
          Input  items are terminated by a null character instead of by whitespace, and the quotes and backslash are
          not special (every character is taken literally).  Disables the end of file string, which is treated  like
          any  other argument.  Useful when input items might contain white space, quote marks, or backslashes.  The
          GNU find -print0 option produces input suitable for this mode.

ls -1用换行符终止项目,因此tr将其转换为空字符。

这种方法比手动迭代要慢大约50倍for ...(请参阅Michael Aaron Safyan的回答)(3.55s vs.0.066s)。但是对于其他输入命令,例如定位,查找,从文件(tr \\n \\0 <file)或类似文件中读取,则必须xargs像这样使用。



1

我喜欢使用gawk在列表上运行多个命令

ls -l | gawk '{system("/path/to/cmd.sh "$1)}'

但是,可转义字符的转义可能会有些毛茸茸。

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.