代码之家  ›  专栏  ›  技术社区  ›  LiraNuna

在已知的文本块中插入一行

  •  2
  • LiraNuna  · 技术社区  · 15 年前

    我将“文本块”定义为文件开头、换行或文件结尾之间的所有行:

    block1
    block2
    block3
    
    anotherblock4
    anotherblock5
    anotherblock6
    
    lastblock7
    lastblock8
    

    任何文本都可以占用一个块-不知道有哪些行。 我试着写一个shell脚本来在第二个块中插入一行,但是由于sed不喜欢使用换行,所以我对这个sed oneliner进行了黑客攻击:

    sed -n "H;\${g;s/\n\n/\nTEST\n\n/2;p}"
    

    结果如下:

    [newline]
    block1
    block2
    block3
    
    anotherblock4
    anotherblock5
    anotherblock6
    TEST
    
    lastblock7
    lastblock8
    

    问题是,它将新行添加到缓冲区的开头(标记为[新行],因为StackOverflow的标记无法显示它) 有没有其他方法可以使用不同的工具或不同的regexp?

    4 回复  |  直到 15 年前
        1
  •  2
  •   Dennis Williamson    15 年前

    这是你想要的,并摆脱不想要的 newline 开始时:

    sed -n "1{x;d};H;\${g;s/\n\n/\nTEST\n\n/2;p}"
    
        2
  •  1
  •   ghostdog74    15 年前

    这里有一个可能的解决方案

    awk '/^$/{f++}f==2{print "TEST\n";f=0;next}1' file
    
        3
  •  0
  •   John Kugelman Michael Hodel    15 年前

    好吧,这不是我最自豪的时刻,但我想它会满足你的需要…也许吧?我没办法 sed 做任何有用的事情,至少在我的机器上,它不喜欢在 s/x/y 替换命令。

    # cat blocks
    block1
    block2
    block3
    
    anotherblock4
    anotherblock5
    anotherblock6
    
    lastblock7
    lastblock8
    # python -c 'import sys,re; print re.sub("(\n\n[\s\S]*?\n)(\n)", "\\1TEST\n\\2", sys.stdin.read(), 1),' < blocks
    block1
    block2
    block3
    
    anotherblock4
    anotherblock5
    anotherblock6
    TEST
    
    lastblock7
    lastblock8
    

    笔记:

    • 没有等价的 塞德 的“替代” 第二 匹配“选项,所以我需要一个更复杂的regex。
    • . 不匹配换行,因此 [\s\S] .
    • 这个 ? 使 * 非贪婪。
    • 第四个参数 1 仅限一次更换。
    • 结尾的逗号禁止 print 添加额外的换行符。

    或者,你可以用大头针 | tail +2 “在几乎但不完全正确之后 塞德 命令切断第一行输出。

        4
  •  0
  •   ephemient    15 年前

    再一个 awk 解决方案。这问 AWK 跟踪段落,而不是像GhostDog74的解决方案那样自己计算它们。

    awk -v 'RS=\n\n' '{print}NR==2{print"TEST"}{print""}'