从多个文件的grep搜索获取最后一行

时间:2013-02-14 22:52:58

标签: shell unix grep

我在使用grep命令时遇到了一些问题。

我找到了只显示grep搜索的最后一行的方法:

grep PATERN FILE_NAME | tail -1

我也找到了在多个选定文件中进行grep搜索的方法:

find . -name "FILE_NAME" | xargs -I name grep PATERN name

现在我想只获取每个文件的grep结果的最后一行。 我试过这个:

 find . -name "FILE_NAME" | xargs -I name grep PATERN name | tail -1

这只返回最后一个文件的最后一个值,我希望每个文件都有最后一个匹配的patern。

11 个答案:

答案 0 :(得分:31)

for f in $(find . -name "FILE_NAME"); do grep PATERN $f | tail -1; done

答案 1 :(得分:3)

这个好先生怎么样

find . -name "FILE_NAME" -print0 | while read -d '' aa
do
  grep PATTERN "$aa" | tail -1
done

答案 2 :(得分:3)

排序有一个uniq选项,允许您从多行中仅选择一行。试试这个:

grep PATTERN FILENAMES* | tac | sort -u -t: -k1,1

说明: Grep将针对文件中的每个匹配项返回一行。看起来像:

$ grep match file*
file1.txt:match
file1.txt:match2
file2.txt:match3
file2.txt:match4

我们想要的是该输出中的两行:

$ ???
file1.txt:match2
file2.txt:match4

您可以将其视为一种表,其中第一列是文件名,第二列是匹配项,列分隔符是':'字符。

我们的第一个管道将输出反转:

$ grep match file* | tac
file2.txt:match4
file2.txt:match3
file1.txt:match2
file1.txt:match

我们要排序的第二个管道说:拔出第一条唯一的行(-u),其中分组依据的键是第一行(-k1,1,键从第1列到第1列),然后拆分将数据分成以“:”作为分隔符(-t :)的列。它还将对我们的输出进行排序!及其输出:

$ grep match file* | tac sort -u -t: -k1,1
file1.txt:match2
file2.txt:match4

答案 3 :(得分:1)

您也可以使用find来执行命令:

find . -name "<file-name-to-find>" -exec grep "<pattern-to-match>" "{}" ";" | tail -1

“{}”是文件名,在编写命令时要注意shell globing和expasion

答案 4 :(得分:0)

您可以从grep&#39; -B(之前)参数开始。例如,在比赛前获得5行:

#include <stdlib.h>

答案 5 :(得分:0)

获取每个文件的最后一行(前缀为文件名)。然后,根据模式过滤输出。

find . -name "*" -exec tail -v -n1 {} \; | grep "some_string" -B1

在macOS上,您必须以稍微不同的方式进行操作

find . -name "*" | xargs tail -1 | grep "some_string" -B1

答案 6 :(得分:0)

可以用awk代替grep来替代。 Posix版本将显示为:

awk '(FNR==1)&&s{print s; s=""}/PATTERN/{s=$0}END{if(s) print s}' file1 file2 file3 ...

使用GNU awk,您可以使用ENDFILE

awk 'BEGINFILE{s=""}/PATTERN/{s=$0}ENDFILE{if(s) print s}' file1 file2 file3 ...

答案 7 :(得分:0)

派对晚了7年。修改命令行的一种慢方法:

find . -name "FILE_NAME" | xargs -I name sh -c "grep PATERN name | tail -1"

如果您需要在每行中显示文件名:

find . -name "FILE_NAME" | xargs -I name sh -c "grep -H PATERN name | tail -1"

答案 8 :(得分:-1)

有一个解决方案,不需要循环,这给了OP想要的东西。

find . -type f -exec sh -c "fgrep print {} /dev/null |tail -1" \;

./tway.pl:print map(lambda x : x[1], filter(lambda x : x[0].startswith('volume'), globals().items()))
./txml.py:           print("%s does not exist: %s\n" % (host, error))
./utils.py:print combine_dicts(a, b, operator.mul)
./xml_example.py:print ET.tostring(root, method="text")

比较没有tail -1为每个文件提供太多行,但证明了上述工作。

find . -type f -exec sh -c "fgrep print {} /dev/null" \;

给出:

./tway.pl:print map(lambda x : x[1], filter(lambda x : x[0].startswith('volume'), globals().items()))
./txml.py:           print("%s resolved to --> %s\n" % (host, ip))
./txml.py:           print("%s does not exist: %s\n" % (host, error))
./utils.py:print "a", a
./utils.py:print "b", b
./utils.py:print combine_dicts(a, b, operator.mul)
./xml_example.py:    print ">>"
./xml_example.py:    print ET.tostring(e, method="text")
./xml_example.py:    print "<<"
./xml_example.py:print ET.tostring(root, method="text")

编辑 - 如果您不希望输出中包含文件名,请删除/ dev / null。

答案 9 :(得分:-1)

查找 last 行的另一种方法是反转文件并输出第一个匹配。

find . -name "FILE_NAME" | xargs -I name sh -c 'tac name|sed -n "/PATTERN/{p;q}"'

答案 10 :(得分:-2)

执行此操作的最快方法是从文件中获取最后一行(或更多)的输出,然后通过它进行grep。所以 -

tail -1 filenames.* | grep "what you want to grep for"