如何在N行内grep倍增字符串

时间:2016-09-13 15:13:28

标签: linux shell command-line grep gawk

我想知道无论如何我都可以用grep(或任何其他命令)搜索N行内的多个字符串。

实施例

搜索" orange"," lime"," banana"全部在3行内

如果输入文件是

xxx
a lime
b orange
c banana
yyy
d lime
foo
e orange
f banana

我想打印以a,b,c开头的三行。 具有搜索字符串的行可以按任何顺序出现。

我不想打印d,e,f行,因为它们之间有一条线,所以这三个字符串没有组合在一起。

3 个答案:

答案 0 :(得分:0)

你的问题还不清楚。这是一个简单的Awk脚本,它收集连续匹配的行并打印iff数组是否超过三个元素。

awk '/orange|lime|banana/ { a[++n] = $0; next }
    { if (n>=3) for (i=1; i<=n; i++) print a[i]; delete a; n=0 }
    END { if (n>=3) for (i=1; i<=n; i++) print a[i] }' file

目前尚不清楚是否需要所有表达式匹配;这个人不会尝试。如果您看到连续三行orange,那就是匹配,并将打印出来。

逻辑应该是直截了当的。数组a收集匹配项,并将n索引到其中。当我们看到不匹配时,我们检查它的长度,如果它是3或更多则打印,然后用空数组和索引重新开始。这也是(笨拙地)在文件末尾重复,以防文件以匹配结束。

如果你想允许间隙(所以,如果有三个连续的行,其中一个匹配“orange”和“banana”,那么一个不匹配,然后一个匹配“lime”,打印这三行?您的问题不清楚)您可以更改为始终保留最后三行的数组,但是您还需要指定如何处理,例如由这些规则匹配的五行序列。

答案 1 :(得分:0)

与tripleee的答案类似,我也会为此目的使用awk。 主要思想是实现一个简单的状态机。

简单示例

作为一个简单的例子,首先尝试找到三个连续的香蕉线。 考虑模式 - 行动声明

/banana/ { bananas++ }

对于匹配正则表达式banana的每一行,它会增加变量bananas(在awk中,所有变量都用0初始化)。

当然,如果有不匹配的行,您希望bananas重置为0,因此您的搜索从头开始:

/banana/ { bananas++; next }
{ bananas = 0 }

您还可以在操作模式中测试变量的值。 例如,如果要在包含banana的三行之后打印“找到”,请扩展​​规则:

/banana/ {
    bananas++
    if (bananas >= 3) {
        print "Found"
        bananas = 0
    }
    next
}

这会将变量bananas重置为0,并打印字符串“Found”。

如何进一步

使用这个基本思想,您应该能够编写自己的awk脚本来处理所有情况。 首先,您应该熟悉awk(模式,操作,程序执行)。

然后,扩展并调整我的示例以满足您的需求。

  • 特别是,您可能需要一个关联数组matched,索引为“banana”,“orange”,“lime”。
  • 当前一行与matched["banana"] = $0匹配时设置/banana/。这将保存当前行以供以后输出。
  • 当前行与任何表达式都不匹配时,清除整个数组。
  • 找到所有字符串后(matched[s]对于每个字符串s都不为空),您可以打印matched[s]的内容。

我将实际的实施留给您。 正如其他人所说,你的描述留下了许多角落不清楚的情况。 你应该自己解决它们并相应地调整你的实现。

答案 2 :(得分:0)

我想你想要这个:

awk '
  /banana/ {banana=3}
  /lime/   {lime=3}
  /orange/ {orange=3}
 (orange>0)&&(lime>0)&&(banana>0){print l2,l1,$0}
 {orange--;lime--;banana--;l2=l1;l1=$0}' OFS='\n' yourFile

因此,如果您看到单词banana,则设置banana=3,以使其对接下来的3行有效。同样,如果您看到lime,则可以为其创建3个机会,同样适用于orange

现在,如果在前三行中看到所有orangelimebanana,则打印倒数第二行(l2),最后一行行(l1)和当前行$0

现在在我们移动到下一行之前递减每个水果的计数,然后保存当前行并按照前两行的时间顺序向后移动。