在文件中打印第一个和最后一个匹配

时间:2014-11-07 16:33:05

标签: bash awk sed grep

以下是否有更清洁的解决方案?

grep INFO messages | head -1
grep INFO messages | tail -1

INFO或消息的长度是随机的。

4 个答案:

答案 0 :(得分:6)

尝试:

grep INFO messages | sed -n '1p;$p'

grep - 将从消息文件中搜索模式 sed -n' 1p; $ p' - 将打印第一(1p)和最后($ p)行

答案 1 :(得分:3)

您可以使用-m来确定您想要的匹配数量:

第一个:

grep -m1 "INFO" messages

最后,让我们用tac向后打印文件,然后使用相同的逻辑:

tac messages | grep -m1 "INFO"

这样,您可以避免处理整个文件两次:您只需处理它直到找到匹配项。


来自man grep

  

-m NUM, - max-count = NUM​​

     

NUM匹配行后停止读取文件。如果输入是   来自常规文件的标准输入和NUM匹配行   输出,grep确保标准输入定位到just   在退出之前的最后一个匹配行之后,无论如何   存在尾随上下文行。这使得调用进程成为可能   恢复搜索。当grep在NUM个匹配行后停止时,它   输出任何尾随上下文行。当-c或--count选项是   也使用,grep不输出大于NUM的计数。当-v   或 - 也使用--invert-match选项,输出后grep停止   NUM个不匹配的行。

man tac

  

tac - 反向连接和打印文件

答案 2 :(得分:2)

这可能是你想要的:

awk '/INFO/{f[++c]=$0} END{ if (c>0) print f[1] ORS f[c] }' messages

或:

awk '/INFO/{f[++c]=$0} END{ if (c>0) print f[1]; if (c>1) print f[c] }' messages

但没有样本输入和预期输出,这是一个猜测。

答案 3 :(得分:1)

我猜你可以使用awk:

awk '/INFO/{a[++i]=$0}END{print a[1];print a[i]}' messages

这会将每个匹配存储在一个数组中,如果匹配很多,这可能是内存消耗的问题。另一种方法是只存储第一个和最近的:

awk '/INFO/{a[++i>2?2:i]=$0}END{print a[1];print a[2]}' messages

或者正如Etan所建议的那样(谢谢):

awk '/INFO/{a=$0}a&&!i++{print}END{if(a)print a}' messages

这个的优势在于,如果没有匹配,则不会打印任何内容。