使用 sed 的正则表达式和管道命令

使用 sed 的正则表达式和管道命令

我发现命令真的很难使用sed,而且我似乎找不到写得好的教程。

假设我在其他语言(Python、JavaScript、Java)中使用过正则表达式,因此不应该成为问题。

所以,这是我的问题(一个“理论”问题和一个更实际的问题):

  1. 正则表达式sed和Python/JS/Java使用的完全一样吗?我读到过有关 BRE 和 ERE 的内容,但它们有多少不同? ERE 不应该是扩大布雷?

  2. 例如,如果我想从管道输出中提取一些内容,sed那么执行此操作的语法是什么?

uptime关于第二个问题的详细信息:假设我有sed的管道输出:

uptime | sed ...

uptime给定:的示例输出18:13 up 5:12, 2 users, load averages: 0,45 0,37 0,40,我想以两个单独的数字(小时和分钟)的形式解析单个正常运行时间,然后我想以xxhyymxx是小时、yy分钟)的形式显示它们。

最后,我将在 Python 中执行以下操作:

hh, mm = re.match(r'\s+ up \s+(\d{1,2}):(\d{1,2})').groups()
print '%sh%sm' % (hh, mm)

答案1

传统的 UNIX 工具支持 BRE 或 ERE(基本或扩展正则表达式)。 POSIX 对两者进行了编码。维基百科他们解释道。大多数现代工具都扩展了 ERE,通常带有首先在 Perl 中引入的附加功能(称为聚合酶链式反应)。

ERE 扩展了 BRE 的功能,但不扩展语法。在BRE中,只有字符\[.*^$具有特殊含义,并且一些运算符(例如分组)\(…\)使用反斜杠。在 ERE 中,+?|()也很特殊,并且反斜杠后跟非字母数字字符从来都不是特殊的。

BRE 没有 Python/PCRE\d\s.您可以使用传统的集合结构和字符类来表示这些字符集:\dis[[:digit:]]\sis [[:space:]]。注意双括号:一个表示字符集,一个表示字符类;例如可以写“字母、破折号或下划线” [-_[:alpha:]]

BRE 没有+运算符(某些 sed 实现支持\+作为 BRE 语法的扩展);X+是相同的XX*。组和匹配计数需要额外的反斜杠。

因此,Python 的 BRE 等效项\s+ up \s+(\d{1,2}):(\d{1,2})[[:space:]][[:space:]]* up [[:space:]][[:space:]]*\([[:digit:]]\{1,2\}\):\([[:digit:]]\{1,2\}\).请注意,您匹配了太多的空白:\s+并且空格表示至少两个空白字符。

您需要匹配整行,因为 sed 的s命令会重写该行。没有单独的命令可以写出从保存的组组装的字符串。纠正额外的空格,Python 代码片段的模拟是:

uptime | sed 's/^.*[[:space:]][[:space:]]*up[[:space:]][[:space:]]*\([[:digit:]]\{1,2\}\):\([[:digit:]]\{1,2\}\).*$/\1h\2m/'

与 Python 代码片段不同,这会提取第一个匹配项而不是最后一个匹配项,但这在这里并不重要。

的输出uptime坚持空格字符和 ASCII 数字,因此您可以简化正则表达式:

uptime | sed 's/^.* up  *\([0-9]\{1,2\}\):\([0-9]\{1,2\}\).*$/\1h\2m/'

uptime这仅匹配机器运行时间少于 1 天的输出。我将留下匹配天数作为练习。 (提示:写两个表达式sed -e s/AS ABOVE/\1h\2m/ -e 's/EXERCISE/\1d\2h\3m/':)

答案2

每个工具(大部分)都使用自己的 RE 库。即使在不同的sed版本中,您也会在这里发现差异。两个流行的标准是 POSIX 标准正则表达式,许多工具都接受这些标准(至少有一些选项),另一个流行的集是 Perl 兼容正则表达式库 (PCRE)。但最后一个与“普通”RE 有很大不同......

在你的情况下:

uptime | sed -e 's/^ \([0-9][0-9]\):\([0-9][0-9]\).*$/\1h\2m/'

(在 Fedora 18、sed-4.2.1-10.fc18.x86_64、GNU sed 上尝试过)。

更新:大量的文档有什么问题GNU sed 的主页?或这个教程? GNU 的信息文档sed有点冗长,但很完整。

相关内容