0

我有一个看起来像这样的文件:

a: 0
a: 0
a: 0
a: 1
b: 1
c: 1
d: 1
e: 1
f: 1
a: 2
b: 2
c: 2
d: 2
e: 2
f: 2
a: 3
b: 3
c: 3
d: 3
e: 3
f: 3
c: 4
c: 4
c: 4

我想捕获并输出表单的所有ac行,<a line><anything other than an a or c line><c line>因此输出如下所示:

a: 1
c: 1

a: 2
c: 2

a: 3
c: 3

请注意,a: 0开头的c: 4行和结尾的行都没有被捕获,因为它们不遵循我提到的模式。另请注意,删除了和b线之间的线。ac

我一直在尝试使用 Bash 的 pcregrep 进行环视,但还没有找到解决方案。有任何想法吗?

谢谢!

4

1 回答 1

4

使用 awk

尝试:

$ awk -F: '$1=="a"{aline=$0} $1=="c"{if(aline)print aline ORS $0 ORS; aline=""}' file
a: 1
c: 1

a: 2
c: 2

a: 3
c: 3

这个怎么运作

默认情况下,awk 一次读取一行。

  • -F:

    这告诉 awk:用作字段分隔符。

  • $1=="a"{aline=$0}

    每次a观察到一行时,将该行保存在变量中aline

  • $1=="c"{if(aline)print aline ORS $0 ORS; aline=""}

    每次c观察一行时,检查我们是否有一个 nonempty aline。如果是这样,打印aline和当前行,用换行符分隔。此外,设置aline回一个空字符串。

多行版本

对于那些喜欢他们的命令分布在几行的人:

awk -F: '
    $1=="a"{
        aline=$0
    }

   $1=="c"{
        if(aline)
            print aline ORS $0 ORS
        aline=""
    }' file

使用 sed

$ sed -n '/^a/h; /^c/{x;/^a/{p;x;s/$/\n/;p};h}' file
a: 1
c: 1

a: 2
c: 2

a: 3
c: 3

这个怎么运作

  • -n

    这告诉 sed 不要打印任何东西,除非我们明确要求它打印。

  • /^a/h

    每当我们有以 开头的行时a,我们都会将其保存到保留空间。

  • /^c/{ x; /^a/{ p; x; s/$/\n/; p}; h}

    每当我们有以 开头的行时c,我们:

    • x我们将 ( ) 模式空间与保持空间交换。

    • 如果新的模式空间以 开头a,那么我们打印 ( p) 它,然后再次交换 ( x),在新模式空间 ( ) 的末尾添加一个新行s/$/\n/并打印 ( p) 它。

    • 最后,我们将当前模式空间(以 a 开头c)保存到保持空间。

于 2019-05-30T19:12:35.347 回答