【问题标题】:Shell: insert a blank/new line two lines above pattern外壳:在模式上方两行插入一个空白/新行
【发布时间】:2010-10-19 22:37:01
【问题描述】:

要在与您的正则表达式匹配的每一行上方添加一个空行,您可以使用:

sed '/regexp/{x;p;x;}'

但我想在与我的正则表达式匹配的行上方添加一个空行,而不是 one 行,而是 two 行。

我将匹配的模式是地址行中的邮政编码。

这是文本格式的 sn-p:

随机信息(属于以前的业务)
企业名称
营业地址

例如:

语言:英语
阿诺德湾,Nfld(克拉伦维尔的附属地)
Nile Road, Arnolds Cove, NL, A0B1N0

我想在公司名称上方添加一个新行:

语言:英语

Nfld 的阿诺德湾(克拉伦维尔附近)
Nile Road, Arnolds Cove, NL, A0B1N0

【问题讨论】:

    标签: python perl text sed awk


    【解决方案1】:

    更具可读性的 Perl,并且可以很好地处理多个文件。

    #!/usr/bin/env perl
    use constant LINES => 2;
    my @buffer = ();
    while (<>) {
        /pattern/ and unshift @buffer, "\n";
        push @buffer, $_;
        print splice @buffer, 0, -LINES;
    }
    continue {
        if (eof(ARGV)) {
            print @buffer;
            @buffer = ();
        }
    }
    

    【讨论】:

      【解决方案2】:

      有点像你在 sed 中的原始方法:

      sed '/regexp/i\
      
      $H
      x'
      

      基本思想是打印延迟一行的所有内容(x更改保持和模式空间 - 打印是隐式的)。这需要完成,因为在我们检查下一行是否与正则表达式匹配之前,我们不知道是否要i插入换行符。

      ($H 只是打印最后一行的技巧。它将最后一行附加到保持缓冲区中,以便最终的隐式打印命令也输出它。)

      【讨论】:

      • 它在所有行之前打印一个空行。
      • 是的,它确实在开头打印了一个空行,因为它输出所有行的保持空间内容,而第一行是空的。添加 '1d' 作为最后一个命令可以消除此问题。
      • ...如果输入只有一行长,则消除所有输出。
      【解决方案3】:

      简单:

      sed '1{x;d};$H;/regexp/{x;s/^/\n/;b};x'
      

      描述一下

      #!/bin/sed
      
      # trick is juggling previous and current line in hold and pattern space
      
      1 {         # at firs line
        x         # place first line to hold space
        d         # skip to end and avoid printing
      }
      $H          # append last line to hold space to force print
      /regexp/ {  # regexp found (in current line - pattern space)
        x         # swap previous and current line between hold and pattern space
        s/^/\n/   # prepend line break before previous line
        b         # jump at end of script which cause print previous line
      }
      x           # if regexp does not match just swap previous and current line to print previous one
      

      编辑:稍微简单一点的版本。

      sed '$H;/regexp/{x;s/^/\n/;b};x;1d'
      

      【讨论】:

      • 仅在内存中保存两行。 hold space 中的上一行和 pattern space 中的当前行。当发现正则表达式时,只需将新行添加到hold space
      • 如果输入只有一行长,这可悲的是根本没有打印出来。
      • @ephemient:对于这个病态输入,使用这个 sed '1{$!{x;d};b};$H;/c\|e/{x;s/^/\n /;b};x'
      【解决方案4】:
      perl -ne 'END{print @x} push@x,$_; if(@x>2){splice @x,1,0,"\n" if /[[:alpha:]]\d[[:alpha:]]\s?\d[[:alpha:]]\d/;print splice @x,0,-2}'
      

      如果我将你的文件放入其中,我会得到你想要的......它很丑陋,但你想要 shell(即单线):-) 如果我用完整的 perl 来做这件事,我会能够对其进行大量清理以使其易于阅读。 :-)

      【讨论】:

        【解决方案5】:

        这是一种适用于 Python 的方法。

        import sys
        def address_change( aFile ):
            address= []
            for line in aFile:
                if regex.match( line ):
                    # end of the address
                    print address[0]
                    print 
                    print address[1:]
                    print line
                    address= []
                 else:
                    address.append( line )
        address_change( sys.stdin )
        

        这使您可以根据自己的喜好重新设置完整地址的格式。如果你的格式很复杂,你可以扩展它来定义一个Address 类。

        【讨论】:

          【解决方案6】:

          我试过了

          sed '/regexp/a\\n'
          

          但它插入了两个换行符。如果那不打扰您,请接受。

          echo -e "a\nb\nc" | sed '/^a$/a\n'
          一个

          b
          c

          编辑: 现在您声明需要在匹配的正则表达式上方插入两行,建议的正则表达式将不起作用。

          我什至不确定它是否适用于 sed,因为您需要记住过去的行。听起来像是 python 或 perl 等高级语言的工作:-)

          【讨论】:

          • 谢谢,我将编辑我的问题以包含 Python 和 Perl 标记(我对 Python 知之甚少,没有 Perl,所以很遗憾我仍然卡住了。)
          猜你喜欢
          • 2011-03-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-01-24
          • 2022-08-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多