【问题标题】:Delete matching nth line until blank line in awk/sed/grep删除匹配的第 n 行直到 awk/sed/grep 中的空白行
【发布时间】:2010-12-16 14:51:31
【问题描述】:

我需要删除文件中从匹配到下一个空白行的第 n 个匹配行(即从第 n 个匹配开始的一大块空白行分隔文本)。

【问题讨论】:

  • 我想我已经理解了这个问题。但是,一个例子可以帮助我回答。
  • 很好的答案。非常感谢。

标签: awk sed grep line


【解决方案1】:

这将删除一段以空行开头和结尾的文本,该空行从第四个空行开始。它还会删除那些分隔线。

sed -n '/^$/!{p;b};H;x;/^\(\n[^\n]*\)\{4\}/{:a;n;/^$/!ba;d};x;p' inputfile

更改第一个/^$/ 以更改开始匹配。更改第二个以更改结束匹配。

鉴于此输入:

aaa
---
bbb
---
ccc
---
ddd delete me
eee delete me
===
fff
---
ggg

这个版本的命令:

sed -n '/^---$/!{p;b};H;x;/^\(\n[^\n]*\)\{3\}/{:a;n;/^===$/!ba;d};x;p' inputfile

会给出这样的结果:

aaa
---
bbb
---
ccc
fff
---
ggg

编辑:

我从上面的sed 命令中删除了一个无关的b 指令。

这是一个注释版本:

sed -n '      # don't print by default
  /^---$/!{   # if the input line doesn't match the begin block marker
    p;        # print it
    b};       # branch to end of script and start processing next input line
  H;          # line matches begin mark, append to hold space
  x;          # swap pattern space and hold space
  /^\(\n[^\n]*\)\{3\}/{    # if what was in hold consists of 3 lines
                           # in other words, 3 copies of the begin marker
    :a;       # label a
    n;        # read the next line
    /^===$/!ba;    # if it's not the end of block marker, branch to :a
    d};       # otherwise, delete it, d branches to the end automatically
  x;          # swap pattern space and hold space
  p;          # print the line (it's outside the block we're looking for)
' inputfile   # end of script, name of input file

任何明确的模式都应该适用于开始和结束标记。它们可以相同也可以不同。

【讨论】:

  • 能否请您评论/分解 sed?
【解决方案2】:
perl -00 -pe 'if (/pattern/) {++$count == $n and $_ = "$`\n";}' file

-00是以“段落”方式读取文件(记录分隔符为一个或多个空行)

$` 是 Perl 的“预匹配”(匹配模式前面的文本)的特殊变量

【讨论】:

    【解决方案3】:

    在 AWK 中

    /m1/  {i++};
    
    (i==3)  {while (getline temp > 0 && temp != "" ){}; if (temp == "") {i++;next}};
    
    {print}  
    

    转换这个:

    m1 1
    first
    
    m1 2
    second
    
    m1 3
    third delete me!
    
    m1 4
    fourth
    
    m1 5
    last
    

    进入这个:

    m1 1
    first
    
    m1 2
    second
    
    m1 4
    fourth
    
    m1 5
    last  
    

    正在删除“m1”的第三个块...

    Running on ideone here

    HTH!

    【讨论】:

      【解决方案4】:

      强制 awk 脚本。只需将 n=2 更改为您的第 n 个匹配项即可。

      n=2; awk -v n=$n '/^HEADER$/{++i==n && ++flag} !flag; /^$/&&flag{flag=0}' ./file
      

      输入

      $ cat ./file
      HEADER
      line1a
      line2a
      line3a
      
      HEADER
      line1b
      line2b
      line3b
      
      HEADER
      line1c
      line2c
      line3c
      
      HEADER
      line1d
      line2d
      line3d
      

      输出

      $ n=2; awk -v n=$n '/^HEADER$/{++i==n&&++flag} !flag; /^$/&&flag{flag=0}' ./file
      HEADER
      line1a
      line2a
      line3a
      
      HEADER
      line1c
      line2c
      line3c
      
      HEADER
      line1d
      line2d
      line3d
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-08-24
        • 2015-05-20
        • 1970-01-01
        • 1970-01-01
        • 2018-08-25
        • 2014-10-07
        • 2012-08-01
        相关资源
        最近更新 更多