我发现命令真的很难使用sed
,而且我似乎找不到写得好的教程。
假设我在其他语言(Python、JavaScript、Java)中使用过正则表达式,因此不应该成为问题。
所以,这是我的问题(一个“理论”问题和一个更实际的问题):
正则表达式
sed
和Python/JS/Java使用的完全一样吗?我读到过有关 BRE 和 ERE 的内容,但它们有多少不同? ERE 不应该是扩大布雷?例如,如果我想从管道输出中提取一些内容,
sed
那么执行此操作的语法是什么?
uptime
关于第二个问题的详细信息:假设我有sed的管道输出:
uptime | sed ...
uptime
给定:的示例输出18:13 up 5:12, 2 users, load averages: 0,45 0,37 0,40
,我想以两个单独的数字(小时和分钟)的形式解析单个正常运行时间,然后我想以xxhyym
(xx
是小时、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
.您可以使用传统的集合结构和字符类来表示这些字符集:\d
is[[:digit:]]
和\s
is [[: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
有点冗长,但很完整。