找到第一个单词后,在下一行中搜索单词

时间:2017-04-06 13:04:17

标签: unix sed grep

我们以此文件textfile.txt

为例
foo
bar
foo
bar
foo**word1**bar
foo
bar**word2**foo
foo
foo
bar
foo**word1**bar
foo
foo
bar**word2**foo
foo
foo
bar
foo**word1**bar
foo
bar**word2**foo
foo
bar
foo**word1**bar
foo
bar
foo
bar
bar**word2**foo
foo

我要做的是:搜索文件中的第一个单词,此处单词为**word1**,如果找到此单词,则搜索同一行,接下来的两个单词搜索第二个单词,这是**word2**

我尝试使用grep搜索**word1**,并使用-n选项获取行号。然后使用此行号,使用sed提取匹配的行和接下来的两行,然后执行其他grep搜索**word2**。它还应该每次**word1****word2**匹配。

但它并不觉得这是实现这一目标的最佳方式。

在这个示例中,应该有3个正面匹配:最后一个不起作用,因为**word2****word1**提前4行,我希望最多前面有2行。

关于awk的输出,我想输出两个单词匹配的行号,以及它们各自找到的行。

我还有一个返回输出的shell脚本。我想做的是:对于每个匹配的几个单词,打印"my_script_result" + "awk_result" > file

3 个答案:

答案 0 :(得分:1)

这个awk单行可能会有所帮助:

awk '/word1/{ok=1}ok && /word2/{print NR,$0}' file

在上面的行中,/word1/是您的第一个单词,/word2/是您的第二个单词。输出将匹配行号和匹配的行。

它以这种方式运作:

脚本从文件开头读取行,找到word1后,设置变量ok =1 (true)。第二部分检查ok AND word2 matched,如果满意,则打印输出。因此,如果在我们找到word2之前匹配word1okfalse,则会跳过该行。

根据OP的更新进行编辑:

awk /word1/{ok=1;s=NR}ok && NR<=s+2 && /word2/{print NR,$0}' file
7 bar**word2**foo
20 bar**word2**foo

答案 1 :(得分:0)

从标记工具中选择grep:

echo shelloutput && grep -nA2 "word1" EgrepToy.txt | egrep "word2"

输出:

shelloutput  
7-bar**word2**foo
20-bar**word2**foo

因为我不确定我是否理解并且#34;在这个例子中,应该有3个正面匹配&#34; (我认为OP和我在某种程度上计算&#34;下一行&#34;不同),我添加一个替代方案来获得三个:

echo shelloutput && grep -nA3 "word1" EgrepToy.txt | egrep "word2"  

输出:

shelloutput  
7-bar**word2**foo  
14-bar**word2**foo  
20-bar**word2**foo  

两种解决方案基本相同:

  • 创建所需的shelloutput echo shelloutput
  • 立即继续grep &&
  • grep代表第一个单词egrep word1
  • 在输出-A2
  • 中包含正确数量的以下行
  • 添加输入文件行号-n
  • grep第二个单词| egrep word2
  • 的结果

回显shelloutput是您想要做的任何事情的占位符。

答案 2 :(得分:0)

从标记工具中选择sed:

echo shelloutput && sed -En "/word1/{/word2/{=;p;};N;/word2/{=;p;};N;s/^.*\n//;/word2/{=;p;};N;s/^.*\n//;/word2/{=;p;}}" EgrepToy.txt

输出:

shelloutput
7  
bar**word2**foo  
14  
bar**word2**foo  
20  
bar**word2**foo  

像这样工作:

  • 创建一些输出echo shelloutput
  • 继续直接发送&&
  • 查找第一个单词/word1/{
  • 寻找第二个字/word2/{
  • 有条件地打印行号并找到行=;p;};
    • 获取下一行N;
    • 删除第一个模式空格行,包括换行符,而不终止s/^.*\n//;
    • 寻找第二个字/word2/{
    • 打印行号=;
    • 打印匹配行p;
  • 字面意思重复两次

如果你想要两个匹配,即只扫描两个跟随行的word2,那么只需重复一次,只需删除一个N;s/^.*\n//;/word2/{=;p;};