【问题标题】:how to print lines matching between two patterns but second pattern existing multiple times in a file using sed command or awk command?如何使用 sed 命令或 awk 命令打印两个模式之间匹配但第二个模式在文件中多次存在的行?
【发布时间】:2024-01-19 18:30:01
【问题描述】:

我有这个输入文件 F1:

Good morning!
Have a nice day;
see you again the next day;
Bye;

我想打印“Have”和“day”之间的行。 我试过这个命令:*sed -n '/Have/,/day/ p*' F1 输出是:祝你有美好的一天 但我也希望打印第二行,因为它也具有相同的“日”模式。 期望的输出: 祝你有美好的一天; 第二天再见;

谁能帮我解决这个问题? 提前致谢。

【问题讨论】:

  • 阅读this。能有帮助吗?如果是,我可以格式化一个漂亮的答案。
  • sed '/Have/,/day/!d' filesed -n '/Have/,/day/p' file 已经有所需的输出。 /.../,/.../ 切换超过 2 行或更多行,它不会在单行上切换。
  • 您的要求完全不清楚。您想从文件中的第一个 Have 打印到最后一个 day 还是从第一个 Have 到不在同一行的第一天,或者从最后一个 Have 到它之后的第一天或其他什么?你想打印文件中这个范围的每一次出现还是只打印第一个或只打印最后一个或其他?如果它们嵌套了会发生什么? edit 您的问题是为了清楚地说明您的要求并提出更好的示例输入并提供相关的预期输出,如果您需要帮助解决您的实际问题。

标签: bash shell unix awk sed


【解决方案1】:

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

sed  '/Have/{:a;x;s/^\(.*\n.*day[^\n]*\).*/\1/p;x;h;d};H;$!d;ba' file

命令/Have/,/day/ 收集Haveday 之间的最短行数,您需要最长的行数吗?如果是这样,这里就是这样的解决方案。

在保留空间中存储第一行包含Have 的行,然后在每次出现单词Have 时删除上一个集合的最后一个day 之后的行并打印它们。在文件结束时再重复一次。

注意如果没有遇到包含day 的行,命令/Have/,/day/ 将收集从包含Have 的第一行到文件末尾的所有行。只有同时满足两个条件时,才会打印上述解决方案。

【讨论】:

    【解决方案2】:

    这应该在awk 中工作。基本上,它进行了 2 次传递 - 这就是为什么 F1 在命令末尾出现两次作为要处理的文件。

    在第一次通过时(FNR==NR),它将第一次出现“Have”的行号保存在s(开始)中,并将最后一次出现的行号保存在e( end) 单词“day”的结尾。

    在第二遍 (FNR!=NR) 中,它会打印 se 之间的行(开始和结束)。

    awk '/Have/&&s==0{s=FNR} /day/&&FNR==NR{e=NR} (FNR!=NR)&&(FNR>=s)&&(FNR<=e)' F1 F1
    

    【讨论】:

      【解决方案3】:

      下面的方法是单向的

      awk '/Have/           { p=1 }
           /day/  && (p==1) { p=2; print; next }
           !/day/ && (p==2) { p = 0 }
           p' <file>
      

      我们在这里所做的是跟踪标签p。如果找到Have,则设置p=1,如果找到day,则设置p=2,同样打印并移至下一行。如果p&gt;1 表示我们找到了day,如果该行不包含day,则将打印标签设置为零,否则打印。

      输出是

      Have a nice day;
      see you again the next day;
      

      这将打印块,直到最后一个day

      表单的输入

      Good morning!
      Have a nice day;
      see you again the next day;
      Bye;
      
      Good morning!
      Have a nice day;
      see you again the next day;
      Bye;
      

      将输出:

      Have a nice day;
      see you again the next day;
      Have a nice day;
      see you again the next day;
      

      【讨论】: