当前位置: 首页>>技术教程>>正文


删除apt-get删除通配符超出预期。为什么?

, , ,

问题描述

昨晚我试图刻录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。安装或删除软件包时,*通常很危险,很少需要。如果您使用*,您应该引用它,但这并不会使它更安全,因为它倾向于选择比您想要的更多的包,这是aptapt-get解释它的方式的结果,而不是pathname expansion的效果。

  • 甚至安全使用*也是often unnecessary

  • 不安全使用are brutal。删除k3b*将删除名称中包含k3的所有包(以及依赖于此类包的每个包)。即使没有b,这也不是一个错字 – 含有k3就足够了,因为b*意味着“零个或多个b”。


当您使用installremovepurge操作运行aptapt-get时,每个后续参数首先被解释为单个包的名称。如果存在具有该确切名称的包,则会对其执行操作。

如果不存在这样的包,aptapt-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-getapt解释图案作为常规expression.3

虽然您可以使用.*匹配任意数量的任何字符 – 而不仅仅是* – 如果它出现在正则表达式的中间,则只需要它。因为模式与包名的任何子串匹配,所以在模式的结尾(或开头)没有意义。

该联机帮助页提到了^$。这些(特别是^)是编写安全,有效模式的关键,可与aptapt-get中的installremovepurge一起使用。

  • ^将正则表达式锚定到整个字符串的开头。 ^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功能。

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/2571.html,未经允许,请勿转载。