问题描述
昨晚我试图刻录CD。由于对k3b感到烦恼而选择使用brasero,我去了k3b。我输入:
sudo apt-get remove k3b
我打了两次标签,看到我的系统上有k3b和k3b-data。假设我在没有k3b的系统上不需要k3b-data,我也想删除它,所以我输入:
sudo apt-get remove k3b*
不幸的是我没有看就打Y确认。它卸载了比k3b和k3b-data更多的东西。它卸载了不适合我的”k3b*”正则表达式的软件包。例如:传输和network-manager
我相当肯定我在k3b和*之间没有空格但我不知道为什么它会删除它所做的一切。有什么关于apt-get我误解了吗?
最佳解决办法
你想要的命令是sudo apt-get remove '^k3b.*'
,因为:
-
您需要
.*
来匹配任何字符,任意次 -
您需要
^
来匹配字符串的开头 -
您需要引用正则表达式以防止bash将
*
解释为通配符
(这个答案完成并总结了qbi和Flimm提供的先前信息)
次佳解决办法
正则表达式*
代表零或任意多个。所以你告诉apt-get
去除任何含有k3
的东西,然后是任何数量的b
,所以基本上所有的东西都含有k3
。如果我在我的系统上尝试你的命令,它想要删除58个包。
sudo apt-get remove -s k3b*
Package k3b is not installed, so not removed
Package k3b-data is not installed, so not removed
Package k3b-dbg is not installed, so not removed
Package libcanberra-gtk3-0 is not installed, so not removed
Package libcanberra-gtk3-0-dbg is not installed, so not removed
Package libcanberra-gtk3-dev is not installed, so not removed
…
The following packages will be REMOVED:
appmenu-gtk ardour audacity brasero brasero-cdrkit firefox-globalmenu
gconf-editor gir1.2-appindicator-0.1 gnome-applets gnome-control-center
…
0 upgraded, 2 newly installed, 58 to remove and 0 not upgraded.
第三种解决办法
请改用sudo apt-get remove ^k3b
。安装或删除软件包时,*
通常很危险,很少需要。如果您使用*
,您应该引用它,但这并不会使它更安全,因为它倾向于选择比您想要的更多的包,这是apt
和apt-get
解释它的方式的结果,而不是pathname expansion的效果。
-
甚至安全使用
*
也是often unnecessary。 -
不安全使用are brutal。删除
k3b*
将删除名称中包含k3
的所有包(以及依赖于此类包的每个包)。即使没有b
,这也不是一个错字 – 含有k3
就足够了,因为b*
意味着“零个或多个b
”。
当您使用install
,remove
或purge
操作运行apt
或apt-get
时,每个后续参数首先被解释为单个包的名称。如果存在具有该确切名称的包,则会对其执行操作。
如果不存在这样的包,apt
和apt-get
将检查参数包含任何共同regular expression metacharacters 2 .
,?
,+
,*
,|
,\[
,^
,或$
的。如果没有,它已经完成 – 没有找到包裹。
如果它确实包含任何这些字符,则将其视为正则表达式并与任何包名称的任何部分进行匹配。它不必匹配整个名称。正如其他人所说,正则表达式中的*
与glob中的*
并不相同。 ?
也没有。在正则表达式中:
-
*
允许前一项出现any number of times – 包括一次或根本不包括 – 而不是一次。 -
?
生成前一项optional – 也就是说,它允许它出现零次或一次。
apt-get(8)(man apt-get
)说:
If no package matches the given expression and the expression contains one of ‘.’, ‘?’ or ‘*’ then it is assumed to be a POSIX regular expression, and it is applied to all package names in the database. Any matches are then installed (or removed). Note that matching is done by substring so ‘lo.*’ matches ‘how-lo’ and ‘lowest’. If this is undesired, anchor the regular expression with a ‘^’ or ‘$’ character, or create a more specific regular expression.
该手册页只提到.
,?
和*
,但它是不完整的,因为+
,|
,[
,^
和$
也足以让apt-get
或apt
解释图案作为常规expression.3
虽然您可以使用.*
匹配任意数量的任何字符 – 而不仅仅是*
– 如果它出现在正则表达式的中间,则只需要它。因为模式与包名的任何子串匹配,所以在模式的结尾(或开头)没有意义。
该联机帮助页提到了^
和$
。这些(特别是^
)是编写安全,有效模式的关键,可与apt
或apt-get
中的install
,remove
或purge
一起使用。
-
^
将正则表达式锚定到整个字符串的开头。^k3b
选择名称以k3b
开头的所有包。 -
$
将正则表达式锚定到整个字符串的末尾。k3b$
将选择名称以k3b
结尾的所有包。
因此,您可以使用此命令安全地删除包:
sudo apt-get remove ^k3b
最后,在您提到的特定情况下,您可能只是自己传递两个名称:
sudo apt-get remove k3b k3b-data
然后你避免所有这些复杂性! (虽然在习惯之后使用^
进行锚定很简单。)或者使用brace expansion,你的shell扩展到上面的命令中:
sudo apt-get remove k3b{,-data}
1这有两个例外:(a)一些选项(例如,-f
,--purge
)被识别,以及(b)一些标点符号出现在参数的末尾,否则将被视为包名称来执行操作可以用来改变所做的事情(例如,sudo apt install ubuntu-desktop^
安装task而不是包,当^
出现在最后)。
2存在其他正则表达式元字符。例如,\
由所有正则表达式的方言支持并且常用。 .
,?
,+
,*
,|
,[
,^
和$
恰好是元字符的APT开发商决定将触发解释为正则表达式(如命名一个确切的封装解决方案后已失败)。
3验证这一点的最简单方法是使用如上所述的-s
选项模拟这种模式的安装或删除。例如,运行apt -s install ^virtualbox
会显示sudo apt install ^virtualbox
会尝试安装包管理器知道其名称以virtualbox
开头的每个包。但是,也可以通过检查the source code来验证此行为。检查cacheset.cc
中的CacheSetHelper::PackageFromRegEx
功能。