50

如何在一个文件中grep并为每个匹配执行一个命令?

文件:

foo
bar
42
foo
bar

例如,我想date为每场比赛执行foo.

以下尝试不起作用:

grep file foo | date %s.%N

怎么做?

4

6 回答 6

47
grep file foo | while read line ; do echo "$line" | date %s.%N ; done

在脚本中更具可读性:

grep file foo | while read line
do
    echo "$line" | date %s.%N
done

对于每一行输入,read将值放入变量$line中,while语句将执行和之间的循环dodone。由于该值现在位于变量中而不是标准输入中,因此我曾经将echo其推回标准输入中,但您可以这样做date %s.%N "$line",假设 date 以这种方式工作。

避免使用for line in `grep file foo`which is similar,因为for总是在空格处中断,这成为读取文件列表的噩梦:

 find . -iname "*blah*.dat" | while read filename; do ....

会失败for

于 2012-11-15T16:39:00.183 回答
21

你真正需要的是一个xargs命令。http://en.wikipedia.org/wiki/Xargs

grep file foo | xargs date %s.%N

在 Cygwin 环境中匹配某些文件并将匹配项转换为完整 windows 路径的示例

$ find $(pwd) -type f -exec ls -1 {} \; | grep '\(_en\|_es\|_zh\)\.\(path\)$' | xargs cygpath -w
于 2013-12-02T14:30:58.777 回答
5
grep command_string file | sh - 
于 2017-10-30T19:30:16.087 回答
3

linux 中有一个有趣的命令:xargs它允许您使用上一个命令(grep、ls、find 等)的输出作为自定义执行的输入,但有几个选项允许您甚至执行自定义并行命令。下面是一些例子:

根据您的问题,以下是如何为file.txt 中的每个“ foo ”匹配打印格式为“ %s.%N ”的日期:

grep "foo" file.txt | xargs -I {} date +%s.%N

一个更有趣的用途是为每个匹配创建一个文件,但在这种情况下,如果匹配相同,则该文件将被覆盖:

grep "foo" file.txt | xargs -I {} touch {}

如果您想将自定义日期连接到创建的文件

grep "foo" file.txt | xargs -I {} touch "{}`date +%s.%N`"

想象匹配是文件名,您想对它们进行备份:

grep "foo" file.txt | xargs -I {} cp {} "{}.backup"

最后对于 xargs 使用 backupName 中的自定义日期

grep "foo" file.txt | xargs -I {} cp {} "{}`date +%s.%N`"

有关xargs并行执行等选项的更多信息,请访问:https ://en.wikipedia.org/wiki/Xargs和日期格式:https ://www.thegeekstuff.com/2013/05/date-command-examples/

额外我发现在这种情况下也有一个正常的命令有用它更简单但不太通用下面是上述示例的等价物:

for i in `grep "foo" test.txt`; do date +%s.%N; done
for i in `grep "foo" test.txt`; do touch ${i}; done
for i in `grep "foo" test.txt`; do touch "${i}`date +%s.%N`"; done
for i in `grep "foo" test.txt`; do cp ${i} "${i}.backup2"; done
for i in `grep "foo" test.txt`; do cp ${i} "${i}.backup2`date +%s.%N`"; done

玩得开心!!!

于 2020-05-22T05:13:05.343 回答
0
    grep search_string files_to_search | sh
于 2020-02-24T08:50:20.760 回答
0

grep 可能需要--line-buffered在匹配时发出每个匹配行的选项,否则它会在打印匹配行之前缓冲多达 4K 字节,这会破坏这里的目标,例如

tail -f source | grep --line-buffered "expression | xargs ...
于 2019-08-05T09:49:10.810 回答