使用sed在两个正则表达式之间打印行

时间:2013-05-16 12:17:16

标签: sed unix

我有一个包含多个部分的文本文件,我想打印其中一个部分。

该文件的一部分看起来像

3. line 3
4. line 4

## Screenshots ##

1. line 1
2. line 2
3. line 3
4. line 4

## Changelog ##

3. line 3
4. line 4

从此我想要检索## Screenshots ##和下一部分开头之间的所有行。这里的下一部分是## Changelog ##,但它可以是任何内容。因此,我们唯一可以依赖的是它将以##开头。

another thread,我找到了以下代码

sed -e "H;/${pattern}/h" -e '$g;$!d' $file

我修改为

sed -e "H;/## Screenshots ##/h" -e '$g;$!d' readme.md

现在,它检索从## Screenshots ##开始的所有行,但它会打印所有行,直到文件末尾。

然后我将它传送到另一个sed喜欢

sed -e "H;/## Screenshots ##/h" -e '$g;$!d' readme.md | sed "/^##/q" 

但现在只打印

## Screenshots ##

无论如何我可以在截图部分打印所有行吗?

4 个答案:

答案 0 :(得分:26)

awk '/pattern/{p=1;print;next} p&&/^##/{p=0};p' file

以“截图”为例:

kent$  awk '/^## Screenshot/{p=1;print;next} p&&/^##/{p=0};p' file
## Screenshots ##

1. line 1
2. line 2
3. line 3
4. line 4

编辑添加说明

awk '/^## Screenshot/{p=1;print;next} : if match pattern, set p=1,print the line,read next line,(stop processing following scripts)
p&&/^##/{p=0}                         : if p==1 and match /##/ again (next section), set p=0
;p' file                              : if p==1, print the line

仅限

sed -n '/## Screensh/,/##/{/Scree/{p;n};/##/{q};p}' file

EDIT2 向sed cmd添加说明

-n                 -> not print
'/## Screen/, /##/ -> match range, I guess you knew it already
{                  -> if in this range
    /Scree/        -> and line matches /Screenshot/
        {p;n};     -> do print line, and read next row (skip doing rest processing)
    /##/           -> if line matches "##"
        q;         -> quit, we have done all printing
    p              -> if we come to here, print the line
}

答案 1 :(得分:9)

sed -n '/## Screenshots ##/,/##/p' readme.md

这将从## Screenshots ##开始打印,直到找到下一个##。如果您不想要上一次##匹配,最简单的是

sed -n '/## Screenshots ##/,/##/p' readme.md |head -n-1

答案 2 :(得分:5)

AWK

使用awk

可以更轻松,更通用地完成此操作
awk '/^##/ { p-- } /^## Screenshots/ { p=1 } p>0' infile

如果您只需要一个部分,则可以执行以下操作:

awk '/^##/ { p=0 } /^## Screenshots/ { p=1 } p' infile

输出:

## Screenshots ##

1. line 1
2. line 2
3. line 3
4. line 4

说明

/^##/ { p-- }               # subtract one from the section counter
/^## Screenshots/ { p=1 }   # set section counter if current line has Screenshot 
p>0                         # print line if section counter greater than 0

SED

sed -n '/^## Screenshots/,/^##/p' infile | sed '$d'

答案 3 :(得分:1)

我只需要过滤掉文件中可以repeat的部分。我说的是dwarfdump的输出。每个部分都以一个名称开头,例如.debug_macro.debug_line。例如,

.debug_info
...
.debug_macro
...
.debug_line
...
.debug_macro
...

这是脚本(以-n运行):

:l1 /^\.debug_macro/ {  # loop that prints a section
    # pattern space holds current line
    # hold space holds contents of current .debug_macro section
    #     up until current line
    $ { p; q }          # print and quit if at the last line
    h                   # initialize hold space (copy first line of the section)
    :l2 n               # loop that adds lines to hold space
    $ {                 # if at the last line...
        /^\./ {         # if at the beginning of a section
            /^\.debug_macro/ {   # if at the beginning of .debug_macro section
                H                # add line to hold space
            }
        }
        /^\./ ! H       # add line if not at the beginning of a section
        x; p            # print hold space
        q               # quit
    }
    /^\./ ! {           # if not at the beginning of a section...
        H               # add line to hold space
        b l2            # branch to :l2
    }
    x; p; x             # print hold space
    b l1                # branch to :l1
}

输出:

.debug_macro
...
.debug_macro
...