9

请帮助我使用 sed。我有一个像下面这样的文件。

START=A
  xxxxx
  xxxxx
END
START=A
  xxxxx
  xxxxx
END
START=A
  xxxxx
  xxxxx
END
START=B
  xxxxx
  xxxxx
END
START=A
  xxxxx
  xxxxx
END
START=C
  xxxxx
  xxxxx
END
START=A
  xxxxx
  xxxxx
END
START=D
  xxxxx
  xxxxx
END

我想获取 START=A, END 之间的文本。我使用了以下查询。

sed '/^START=A/, / ^END/!d' input_file

这里的问题是,我得到

START=A
  xxxxx
  xxxxx
END
START=D
  xxxxx
  xxxxx
END

代替

START=A
  xxxxx
  xxxxx
END

Sed 贪婪地发现。

请帮我解决这个问题。

提前致谢。

我可以使用 AWK 来实现上述目标吗?

4

3 回答 3

26
sed -n '/^START=A$/,/^END$/p' data

-n选项表示默认不打印;然后脚本说'在包含的行START=A和下一行之间打印END

你也可以这样做awk

一个模式可能由两个用逗号分隔的模式组成;在这种情况下,对从第一个模式的出现到第二个模式的出现的所有行执行该操作。

(来自man awkMac OS X)。

awk '/^START=A$/,/^END$/ { print }' data

给定问题中数据文件的修改形式:

START=A
  xxx01
  xxx02
END
START=A
  xxx03
  xxx04
END
START=A
  xxx05
  xxx06
END
START=B
  xxx07
  xxx08
END
START=A
  xxx09
  xxx10
END
START=C
  xxx11
  xxx12
END
START=A
  xxx13
  xxx14
END
START=D
  xxx15
  xxx16
END

使用 GNUsed或 Mac OS X (BSD)sed和使用 GNUawk或 BSD的输出awk是相同的:

START=A
  xxx01
  xxx02
END
START=A
  xxx03
  xxx04
END
START=A
  xxx05
  xxx06
END
START=A
  xxx09
  xxx10
END
START=A
  xxx13
  xxx14
END

请注意我如何修改数据文件,以便更容易查看打印的各种数据块在文件中的来源。

如果您有不同的输出要求(例如“仅在 START=A 和 END 之间的第一个块”,或“仅最后一个 ...”),那么您需要在问题中更清楚地表达这一点。

于 2013-05-20T05:51:35.837 回答
3

基础版...

sed -n '/START=A/,/END/p' yourfile

更强大的版本...

sed -n '/^ *START=A *$/,/^ *END *$/p' yourfile
于 2013-05-20T06:15:09.833 回答
2

您的sed表达式在结束前有一个空格,即/ ^END/. 所以sed得到起始图案,但没有得到结束图案并继续打印直到结束。使用sed '/^START=A/, /^END/!d' input_file(注意/^END/

于 2013-05-20T06:07:24.533 回答