代码之家  ›  专栏  ›  技术社区  ›  Chen Levy

不包括sed/start/,/end中的第一行和最后一行/

  •  39
  • Chen Levy  · 技术社区  · 16 年前

    考虑输入:

    =sec1=
    some-line
    some-other-line
    
    foo
    bar=baz
    
    =sec2=
    c=baz
    

    如果我只想处理=sec1=我可以通过以下方式注释该部分:

    sed -e '/=sec1=/,/=[a-z]*=/s:^:#:' < input
    

    …嗯,差不多。

    这将对行进行注释 包括 “=sec1=”和“=sec2=”行,结果如下:

    #=sec1=
    #some-line
    #some-other-line
    #
    #foo
    #bar=baz
    #
    #=sec2=
    c=baz
    

    我的问题是: 在SED中,从a/start/、/end/范围中排除开始行和结束行的最简单方法是什么? ?

    我知道在很多情况下,“s:::”爪的精化可以在这个特定的情况下给出解决方案,但我在这里追求通用的解决方案。

    在“ Sed - An Introduction and Tutorial 布鲁斯·巴内特写道:“我稍后会告诉你如何将命令限制在,但不包括包含指定模式的行。”但我找不到他实际显示的位置。

    在“ USEFUL ONE-LINE SCRIPTS FOR SED “由Eric Pement编译,我只能找到包容性示例:

    # print section of file between two regular expressions (inclusive)
    sed -n '/Iowa/,/Montana/p'             # case sensitive
    
    5 回复  |  直到 8 年前
        1
  •  36
  •   Ville Laurikari    16 年前

    这应该可以做到:

    sed -e '/=sec1=/,/=sec2=/ { /=sec1=/b; /=sec2=/b; s/^/#/ }' < input
    

    这将包含在sec1和sec2之间匹配,然后跳过第一行和最后一行 b 命令。这会在sec1和sec2之间留下所需的行(不包括),并且 s 命令添加注释符号。

    不幸的是,您需要重复regexps来匹配分隔符。据我所知,没有比这更好的方法了。至少可以保持regexp的干净,即使它们被使用了两次。

    这是改编自 SED FAQ: How do I address all the lines between RE1 and RE2, excluding the lines themselves?

        2
  •  13
  •   MikhailVS    13 年前

    如果您对超出范围的行不感兴趣,但只想从问题(这就是为什么我来到这里)中得到爱荷华州/蒙大拿州示例的非包容变体,您可以用第二个sed轻松地编写“除了第一个和最后一个匹配行”子句:

    sed -n '/PATTERN1/,/PATTERN2/p' < input | sed '1d;$d'

    就我个人而言,我发现这比同等文件更清楚(尽管在大型文件中速度较慢)

    sed -n '1,/PATTERN1/d;/PATTERN2/q;p' < input

        3
  •  6
  •   MikhailVS    13 年前

    另一种方法是

    sed '/begin/,/end/ {
           /begin/n
           /end/ !p
         }'
    

    /begin/n ->跳过具有“开始”模式的行
    /end/ !p ->打印没有“结束”图案的所有行

    摘自布鲁斯·巴内特的SED教程 http://www.grymoire.com/Unix/Sed.html#toc-uh-35a

        4
  •  1
  •   ghostdog74    16 年前

    你也可以用锥子

    awk '/sec1/{f=1;print;next}f && !/sec2/{ $0="#"$0}/sec2/{f=0}1' file
    
        5
  •  1
  •   Maxim_united    8 年前

    我曾经用过:

    sed '/begin/,/end/{/begin\|end/!p}'
    

    这将搜索模式之间的所有行,然后打印不包含模式的所有内容。