我想知道无论如何我都可以用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行,因为它们之间有一条线,所以这三个字符串没有组合在一起。
答案 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
。
现在,如果在前三行中看到所有orange
,lime
和banana
,则打印倒数第二行(l2
),最后一行行(l1
)和当前行$0
。
现在在我们移动到下一行之前递减每个水果的计数,然后保存当前行并按照前两行的时间顺序向后移动。