12

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

文件的一部分看起来像

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 ##,但它可以是任何东西。所以我们唯一可以依赖的是它会以##.

另一个线程,我找到了以下代码

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

4 回答 4

27
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

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
}
于 2013-05-16T12:37:43.057 回答
10

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

这将从找到## Screenshots ##下一个开始打印##。如果你不想要最后##一场比赛,最简单的是

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

于 2013-05-16T12:39:08.593 回答
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'
于 2013-05-16T12:26:47.847 回答
2

我只需要过滤掉可以重复的文件部分。我说的是输出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
...
于 2018-09-08T20:27:32.110 回答