我想从这里提取已删除包的名称“cat /var/log/dpkg.log | grep 'remove'”
2013-09-09 15:57:34 remove activity-log-manager:i386 0.9.4-0ubuntu6.2 <none>
2013-09-09 15:57:35 remove activity-log-manager-control-center:i386 0.9.4-0ubuntu6.2 <none>
2013-09-09 15:57:38 remove alacarte:all 3.6.1-0ubuntu3 <none>
2013-09-09 15:57:41 remove deepin-software-center:all 2.1.2.1~precise~NoobsLab.com <none>
Run Code Online (Sandbox Code Playgroud)
我只想在包名称之后获取 remove 和冒号之间的包名称。我不是正则表达式专家,我做了一个正则表达式似乎可以完成这项工作,但是当我想用 grep 应用它时,什么也没有发生。这是正则表达式评估器中的工作正则表达式模式
(?<=remove)(.*?)(?=:)
Run Code Online (Sandbox Code Playgroud)
但这不起作用:
cat /var/log/dpkg.log | grep 'remove' | grep '(?<=remove)(.*?)(?=:)'
Run Code Online (Sandbox Code Playgroud)
我在这里缺少什么?
正则表达式语法有一个共同的核心,但也有不同的风格。您的表达式似乎包含特定于 perl 风格的一些功能,特别是使用复杂的环视断言来描述要匹配的模式的开始和结束,而 grep 默认为基本正则表达式 (BRE) 语法,该语法仅支持更简单的这些零长度匹配的集合,例如 line- ( ^, $) 和 word-anchors ( \>, \<)。
您可以使用 -P 命令行开关在 grep 中启用与 perl 兼容的正则表达式 (PCRE) 支持(但请注意,手册页当前将其描述为“实验性”)。在您的情况下,您可能还希望 -o 开关也只打印匹配的模式,而不是整行,即
cat /var/log/dpkg.log | grep 'remove' | grep -oP '(?<=remove)(.*?)(?=:)'
Run Code Online (Sandbox Code Playgroud)
请注意,如果此表达式遇到没有 :i386 后缀的包,它可能会失败,因为它可能会提前读取下一个单词中的匹配冒号,例如
echo "2013-09-07 08:31:44 remove cifs-utils 2:5.1-1ubuntu2 <none>" | grep -oP '(?<=remove)(.*?)(?=:)'
cifs-utils 2
Run Code Online (Sandbox Code Playgroud)
您可能希望查看 awk,例如
cat /var/log/dpkg.log | awk '$3 ~ /remove/ {sub(":.*", "", $4); print $4}'
Run Code Online (Sandbox Code Playgroud)
除了 BRE 和 PCRE 之外,Gnu grep 还有一种称为扩展正则表达式(ERE) 的模式,由 -E 命令行开关指定。手册页指出
In GNU grep, there is no difference in available functionality
between basic and extended syntaxes.
Run Code Online (Sandbox Code Playgroud)
但是你要注意,“在提供的功能没有差别”并不能意味着语法是相同的。例如,在 BRE 中,+字符通常被视为文字,如果转义,则仅成为修饰符,表示“前面的正则表达式的一个或多个实例”,即
$ echo "123.456" | grep '[0-9]+\.[0-9]+'
$ echo "123.456" | grep '[0-9]\+\.[0-9]\+'
123.456
Run Code Online (Sandbox Code Playgroud)
而对于 ERE 则恰恰相反
$ echo "123.456" | grep -E '[0-9]+\.[0-9]+'
123.456
$ echo "123.456" | grep -E '[0-9]\+\.[0-9]\+'
Run Code Online (Sandbox Code Playgroud)
类似的区别适用于sed不带-r开关和带开关的调用。