【问题标题】:Remove text/lines between search patterns删除搜索模式之间的文本/行
【发布时间】:2020-12-17 09:45:45
【问题描述】:

删除整行的编码很容易,但我想弄清楚如何在 reg 表达式之间删除。我写了一个更有趣的例子,而不是我正在处理的技术报告:

当前文本:

 cactus in the desert blooms @year round
 and almost all cactus plants have very sharp needles
 ------ that may hurt you if you get too close-----
 so stay away from the needles all @year and admire the 
     many colors in the buds @and flowers

 more data more data more data

 cactus in the desert blooms @year round
 and almost all cactus plants have very sharp needles
 so stay away from the needles all @year and admire the 
 data more data more data @year
 data more data more data more data @year
     many colors in the buds @and flowers
more data
 cactus in the desert blooms @year round
 and almost all cactus plants have very sharp needles
    so stay away from the needles all @year and admire the 
     many colors in the buds @and flowers

more data more data
more data more data
more data more data

在这种情况下,我使用@year 作为初始reg 表达式,@and 作为第二个。我想删除 reg 表达式之间的删除部分和完整行。更喜欢使用 SED。

注意:@year 的任何后续实例都需要被忽略,直到找到 @and。如果找到多个@and 实例,则不应执行任何操作,因为之前没有@year 实例。

显示的所有示例都需要结果:

 cactus in the desert blooms and flowers

 more data more data more data

 cactus in the desert blooms and flowers
 more data more data more data

 cactus in the desert blooms and flowers
 more data
 cactus in the desert blooms and flowers

 more data more data
 more data more data
 more data more data

【问题讨论】:

  • 能否让我们知道您是否可以多次出现 @and ?如果是,那么您是否要匹配到它的最后一次出现或它的任何特定实例?或者您的实际 Input_file 中是否只有这些确切的行,如显示的样本本身?请确认一次。
  • 您的示例和文本要求中缺少此类问题的所有常见用例,例如如何在@and之前处理2个@years,在一个@year之后处理2个@ands,一个@and前面没有@year,一个@year没有后续@and,等等您将获得针对您展示的一个晴天案例的解决方案 - 您的输入中始终有一个 @year@and 对。如果这不是您所需要的,那么 edit 您的问题会澄清您的要求并提供更实际的示例输入/输出。
  • 您还得到了假设 @ 不能出现在您输入的任何其他位置的解决方案,因为它没有出现在您发布的示例中。如果这是一个错误的假设,那么edit 您的示例再次包含更多@s(以及@year@and 可以作为子字符串出现的情况,例如joe@andoverplumbers.com 等)
  • 该文件包含自然出现的@ 符号,但我使用 SED 将这些符号替换为空间。我将交换@year@and。正则表达式@and 肯定是一致的。但是,由于我必须进行交换以插入@year,因此在@and 出现在文件中之前,它可能会在不同的行上出现多次。所以首先找到@year时需要打开搜索,找到@and后关闭搜索。我会将其添加到我的示例中。
  • 如果您问题中的示例未涵盖您的所有用例,请编辑您的问题以显示更真实的示例。另外,不要在 cmets 中添加文本要求 - edit 您的问题要包含所有相关信息。

标签: awk sed


【解决方案1】:

您能否完全根据您在 GNU awk 中显示的示例尝试关注。 如果您的 Input_file 中没有任何空行,请尝试。

awk -v RS= '{sub(/@year.*@and/,"and")} 1' Input_file

显示的示例输出将是:

 cactus in the desert blooms and flowers

【讨论】:

  • sub 很贪心,可能会一口气吸收多个段落。
  • @kvantour,同意,但这就是为什么我写了“它按照所示示例编写”,如果 OP 附带一些示例/示例,其中它需要在这个示例/示例中需要其他内容,那么然后编辑答案。
  • @kvantour,我给 OP 留下了评论,让我们看看 OP 怎么说。
  • 您显示的"and" 是否引用@and?或者不管@year@and 这两个正则表达式是否都应该是文字。如果正则表达式是@year@limit,那么"and" 还会在那里还是会变成"limit"
  • @985ranch,基本上它是根据您显示的示例编写的,它将整个 para 视为一行,并简单地用 and 替换 @year@and,这会产生您的示例输出。跨度>
【解决方案2】:

使用名为cactus 的文件,您可以:

$ sed ':a; N; s/\n/ /; ta' cactus | sed 's/[@][^@][^@]*[@]//'
 cactus in the desert blooms and flowers

"cactus" 之前的前导 ' ' 仍然存在,您可以根据需要删除。

在第二个表达式上使用扩展正则表达式可简化为:

sed ':a; N; s/\n/ /; ta' cactus | sed -E 's/@[^@]+@//'

【讨论】:

  • 但这不会改变文件中分隔符前后的行吗?
  • 您可以根据需要收紧或缩小搜索范围。只需将删除更改为,例如's/@year[^@]+@and/and/' 将限制@year@and 之间的删除,并用and 代替它。使用 BRE,即 sed 's/@year[^@][^@]*@and/and/'
【解决方案3】:

使用 GNU sed for -z:

$ sed -z 's/@year.*@and/and/' file
 cactus in the desert blooms and flowers

【讨论】:

  • 别忘了提到.* 是贪婪的,所以如果文件中有两组或更多组@year@and,此解决方案将删除第一个@year 和最后一个@and
  • 我没有忘记,我在问题下评论说问题中缺少许多潜在的用例,因此 OP 只是获得适用于所示一个晴天案例的解决方案。例如,您的答案假设 OP 想要删除 @year第一个 @and 之间的文本。也许他们想从第一个 @year 删除到最后一个 @and 或其他内容。除了问题中的一个晴天案例,我们只是不知道 OP 想要做什么。
  • 这非常接近。当只找到@and 时,它通过了案例,这很好。当它找到两个正则表达式并采取行动时,它确实删除了行和中间的部分行,但是接下来的几行是一个空行,并且空行下面的所有行也被删除了。
  • 当我将"and" 保留为文字时,它并没有删除文件的其余部分,因此将其更改为类似于正则表达式是我不理解的,但是部分行没有被删除.当@year 出现,然后在下一行出现另一个@year,然后@and 出现时,它并没有删除从@year@and 的第一个实例中的所有内容。
  • 发布的所有解决方案都旨在与您展示的示例一起使用,仅此而已。你不应该期望它们中的任何一个可以处理你没有展示的任何东西。听起来您确实需要考虑所有常见用例(请参阅问题下的我的 cmets),因此请描述您希望如何处理它们,并将它们包含在问题的示例中,如果您想要一个解决方案来处理您想要处理的每个案例。跨度>
【解决方案4】:

使用 Perl,

$ cat ranch.txt
 cactus in the desert blooms @year round
 and almost all cactus plants have very sharp needles
 ------ that may hurt you if you get too close-----
 so stay away from the needles and admire the
     many colors in the buds @and flowers
$ perl -0777 -pe ' s/(?:\@year)(.+)(?:\@and)/and/gms ' ranch.txt
 cactus in the desert blooms and flowers
$

【讨论】:

    【解决方案5】:

    假设每一行中最多有一个@,我将使用GNU AWK,让file.txt内容为:

     cactus in the desert blooms @year round
     and almost all cactus plants have very sharp needles
     ------ that may hurt you if you get too close-----
     so stay away from the needles and admire the 
         many colors in the buds @and flowers
    

    然后

    awk 'BEGIN{FS="@";ORS="";doprint=1}
    (NF<=1){if(doprint)print}
    (NF>1){doprint=!doprint;print doprint?$2:$1}' file.txt
    

    输出

     cactus in the desert blooms and flowers
    

    解释:我将字段分隔符设置为@,并将记录分隔符设置为空(空字符串)并将doprint 设置为true。然后对于不超过1个字段的每一行(即没有@)我只是print它如果doprint成立并且对于每行超过1个字段(即持有@)我否定doprint,然后如果它被设置为真,我打印超出@ 的内容,否则打印@ 之前的内容。

    【讨论】:

      【解决方案6】:

      还有awk:

      awk 'BEGIN{FS="@";ORS=""} /@year/ {print $1} /@and/{print $2"\n"}' file
      cactus in the desert blooms and flowers
      

      【讨论】:

      • 此命令似乎只是将文件中的每一行替换为单词“and”。
      • 对不起。输入数据已更改!这段用gnu-awk 测试的代码仅适用于之前的输入数据。
      【解决方案7】:

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

      sed ':a;/@year/{:b;/@and/!{N;bb};s/\n//g;s/@year/\n/;s/@and/\nand/;s/\n.*\n//;ba}' file
      

      在包含@year@and 的模式空间中收集行。

      删除集合中的所有换行符。

      @year 替换为\n,将@and 替换为\nand

      删除引入的换行符之间的所有内容。

      重复。

      注意这将满足同一行上的两组或多组开始和结束分隔符。

      【讨论】:

        猜你喜欢
        • 2016-04-30
        • 1970-01-01
        • 1970-01-01
        • 2016-05-03
        • 2021-10-15
        • 2019-06-01
        • 1970-01-01
        • 2021-07-02
        • 1970-01-01
        相关资源
        最近更新 更多