我有一个用于在 Linux 中查找特定已安装软件包的基本脚本。如果未找到 -> 打印软件包。
我使用了grep -w
,但是它不能正常与-
角色配合使用。
例如,
dpkg -l | grep -w "rpm"
还会发现rpm-common
。
我找到了使用正则表达式的解决方案。问题是它在 Bash 脚本中不起作用。
解决方案:
dpkg -l | grep -E '(^|\s)string($|\s)'
健康)状况:
if [ `dpkg -l | grep -E '(^|\s)$i($|\s)' | wc -l` = 0 ]; then echo$i; fi
$i
指的是数组值,例如arr[index]=$i
。
我需要使用哪些转义字符才能使条件起作用?
答案1
这里有两个问题:正如@AFH 指出的那样,\s
是 Perl 简写,不是标准 POSIX 语法的一部分。表示它的标准方法是使用字符类[[:space:]]
。第二个问题是变量引用不会在单引号内展开;您需要使用双引号(并转义$
正则表达式的一部分)。
此外,还有一些风格建议:$( )
通常比反引号更适合用于命令替换(它更容易阅读,并且没有反引号所具有的一些奇怪的转义语法怪癖)。但在这种情况下,您可以跳过命令扩展;而不是使用wc -l
并与零进行比较以查看是否有任何匹配项,只需使用grep
的退出状态作为测试(以及-q
阻止其打印匹配项的选项)。此外,请务必双引号引用变量引用(例如在命令中echo
)。
以下是我建议的重写版本:
if dpkg -l | grep -Eq "(^|[[:space:]])$i(\$|[[:space:]])"; then echo "$i"; fi
编辑:正如 igor 在评论中指出的那样,这不适用于包含正则表达式元字符的包名称(如 g++-5)。可以预处理包名称以转义元字符,但这相当混乱。但有一种更简单的方法:如果您使用的是 bash(而不是其他 shell),则可以使用 bash 的本机正则表达式功能直接进行匹配:
if [[ "$(dpkg -l)" =~ (^|[[:space:]])"$i"(\$|[[:space:]]) ]]; then echo "$i"; fi
其之所以有效,是因为$i
模式中间的 用双引号引起来,这告诉 bash 将其作为文字字符串进行匹配(即忽略其中的任何正则表达式元字符)。
答案2
扩展正则表达式不支持\s
,但 Perl RE 支持,因此请尝试使用-P
而不是-E
:
dpkg -l | grep -P '(^|\s)rpm($|\s)'
看此引用了解更多信息。
手册grep
上说这-P
是实验性的,但它在 Ubuntu 16.04 上对我有用。