【问题标题】:how can I find a matching pattern between two words using sed or awk如何使用 sed 或 awk 在两个单词之间找到匹配模式
【发布时间】:2016-02-12 03:16:56
【问题描述】:

我想在段落中搜索以 word1 开头并以 word2 结尾的模式,如果模式匹配,则打印段落的第一行,我不确定是否可以使用 grep 例如,如果我有以下文件并且我正在寻找 aaa

Word1 this is paragraph number 1 
aaa
bbb
ccc
word2

Word1 this is paragraph number 2 
bbb
ccc
ddd
word2

答案应该是这样的

Word1 this is paragraph number 1

【问题讨论】:

    标签: awk sed grep


    【解决方案1】:

    这可能对你有用(GNU sed):

    sed -n '/^Word1/!b;:a;N;/^word2/M!ba;/^aaa/MP' file
    

    忽略任何不以Word1 开头的行。收集模式空间中的行,直到以word2 开头的行或文件结尾。如果进行了匹配,则还要匹配所需的字符串(在本例中为 aaa)。如果匹配,则打印第一行并重复。

    编辑:如果段落可以以其他词结尾,即word3,请使用:

    sed -n '/^Word1/!b;:a;N;/^$/Mb;/^word2/M!ba;/^aaa/MP' file
    

    【讨论】:

    • @123 见here
    • 它假定所有段落都以word2 结尾。如果没有出现该前提条件,则该命令将在前面的word1 和后面的word2 之间的每一行中匹配aaa,尽管它们属于不同的段落。
    • @Birei 从问题的编写方式来看,我认为感兴趣的段落以word1 开头并以word2 结尾。但是,请参阅编辑以获取修改后的解决方案以供您解释。
    • 是的。根据接受的答案,您的解释似乎是正确的,有类似的问题,并且适用于 OP。
    【解决方案2】:

    这是简单、惯用的 awk 解决方案:

    $ awk -v RS= -F'\n' '/^Word1.*aaa.*word2$/{print $1}' file
    Word1 this is paragraph number 1
    

    如果这不能满足您的要求,请编辑您的问题以阐明您的要求。

    【讨论】:

      【解决方案3】:

      你可以试试这个awk:

      awk '/^Word1/{f=1;l="";hold=$0} /word2$/{f=0; if(l ~ /aaa/){print hold}} f{l = l RS $0}' file
      

      【讨论】:

      • 并非适用于所有情况,因为word2 假定在每个段落中。例如,添加两个额外的段落,一个以word1 开头并以word4 结尾,另一个以word7 开头并以word2 结尾。如果aaa 仅在第二个中找到,它将打印第一个的标题,因为它尝试匹配word1word2 之间的所有行,尽管它们属于不同的段落。
      • 这与执行要求的操作还差得远。当然,给定发布的示例输入,它会产生发布的预期输出,但这只是因为发布的示例输入没有经过深思熟虑。当您的段落仅包含 word1 和 word2 而不是以它们开头时尝试一下。当 word1 根本不存在时尝试一下。当 word1 在 1 个段落中而 word2 在另一个段落中时尝试它。
      • 好吧,至少现在它在 line 的开头/结尾检查 word1/word,但仍然没有在 的开头/结尾检查它>paragraph 并且它仍然不检查 ​​2 个单词在哪个段落中。尽管如此,OP 似乎对此很满意......
      【解决方案4】:

      试试这个 AWK:

       awk '/Word1/{l=$0;flag=1;next}/word2/{flag=0}flag && $0 ~ /aaa/ && !c{print l; c++}' file
      

      输入:

      Word1 this is paragraph number 1 
      aaa
      aaa
      bbb
      aaa
      word2
      
      Word1 this is paragraph number 2 
      bbb
      ccc
      ddd
      word2
      

      输出:

      Word1 this is paragraph number 1
      

      【讨论】:

      • 它正在工作,但我想将找到该模式的段落的第一行作为输出
      • @malmo 我没有尝试过我以前的脚本,这是错误的!脚本语法不正确。现在好了
      • 在打印标题行之前,您的命令是否等待检查段落是否以word2 结尾?而且,如果每个段落中有很多行带有aaa 怎么办?它将为每个匹配打印一次标题。
      • @Birei 是真的。我检查的是 Word2 而不是 word2。现在如果有多个模式只打印一个标题
      【解决方案5】:

      一个简单的解决方案(与您要求的不完全匹配):

      awk -F'\n' -v RS= '/bbb/{print $1}' file
      

      这会跳过查找 Word1/Word2,并假设您在示例中的记录之间有一个空行。

      当然,您总是可以事先使用 sed 强制空行:

      gsed 's/^Word1/\n&/' file | ...above...
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-20
        • 1970-01-01
        • 2016-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-07
        • 1970-01-01
        相关资源
        最近更新 更多