apt-get删除与通配符删除方式比预期更多。 为什么?

昨晚我试图刻录CD。 由于对k3b感到恼火而选择使用brasero,我去了k3b。 我输入:

sudo apt-get remove k3b 

我打了两次标签,发现我的系统上有k3b和k3b数据。 假设我在没有k3b的系统上不需要k3b数据,我想删除它,所以我输入:

 sudo apt-get remove k3b* 

不幸的是我没有看就打Y确认。 它卸载了比k3b和k3b数据更多的东西。 它卸载了不适合我的“k3b *”正则表达式的软件包。 例如:传输和网络管理器

我很确定我在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解释它的方式的结果,而不是 路径名扩展的影响。

  • 甚至安全使用* 通常是不必要的 。
  • 不安全的用途是残酷的 。 删除k3b*将删除名称中包含k3每个包(以及依赖于此类包的每个包)。 这不是一个错字 – 包含k3就足够了,即使没有b ,因为b*意味着“零或更多b s”。

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

如果没有这样的包, aptapt-get将检查参数是否包含任何常见的正则表达式 元字符 2 .?+*|\[^$ 。 如果没有,它已经完成 – 没有找到包裹。

如果它确实包含任何这些字符,则将其视为正则表达式并与任何包名称的任何部分进行匹配。 它不必匹配整个名称。 正如其他人所说, *在正则表达式中并不意味着与glob中的*相同。 ? 也没有。 在正则表达式中:

  • *允许前一项出现任意次数 – 包括一次或根本不出现 – 而不是一次。
  • ? 使前一项可选 – 也就是说,它允许它出现零次或一次。

apt-get(8) ( man apt-get )说:

如果没有包与给定的表达式匹配,并且表达式包含’。’,’?’之一 或者’*’然后它被假定为POSIX正则表达式,并且它被应用于数据库中的所有包名称。 然后安装(或删除)任何匹配项。 请注意,匹配由子字符串完成,因此’lo。*’匹配’how-lo’和’lowest’。 如果这是不期望的,请使用“^”或“$”字符锚定正则表达式,或者创建更具体的正则表达式。

该联机帮助页仅提及.?* ,但它不完整 ,如+|[^$也足以让apt-getapt将模式解释为正则表达式。 3

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

联机帮助页提到了^$ 。 这些(尤其是^ )是编写安全,高效模式的关键,可用于aptapt-getinstallremovepurge操作。

  • ^将正则表达式锚定到整个字符串的开头^k3b选择名称以k3b 开头的所有包。
  • $将正则表达式锚定到整个字符串的末尾k3b$将选择名称以k3b 结尾的所有包。

因此,您可以使用此命令安全地删除包:

 sudo apt-get remove ^k3b 

最后,在您提到的特定情况下,您可能只是自己传递两个名称:

 sudo apt-get remove k3b k3b-data 

然后你避免所有这些复杂性! (虽然在习惯之后用^锚定很简单。)或者使用大括号展开 ,你的shell扩展为上面的命令:

 sudo apt-get remove k3b{,-data} 

1 这有两个例外: (a)一些选项(例如, -f , – --purge )被识别,以及(b)一些标点符号出现在一个参数的末尾 ,否则将被视为一个包名称执行动作可以用来改变所做的事情(例如, sudo apt install ubuntu-desktop^安装任务而不是包,当^出现在最后)。

2 存在其他正则表达式元字符。 例如,所有正则表达式的方言都支持\且常用。 . ? +*| [^$恰好是APT开发人员决定将触发解释为正则表达式的元字符(在作为命名的精确包失败后解析)。

3 validation这一点的最简单方法是使用如上所述的-s选项模拟使用这种模式的安装或删除。 例如,运行apt -s install ^virtualbox显示sudo apt install ^virtualbox会尝试安装包管理器知道其名称以virtualbox开头的每个包。 但是,也可以通过检查源代码来validation此行为。 检查CacheSetHelper::PackageFromRegEx函数。

您可能会删除其中包含k3b的lib,这些程序依赖于这些程序。

总之,你可能永远不会知道。 我建议不要使用通配符来删除内容并在提示时阅读内容(抱歉)。

同样没有-n正则表达式搜索使用所有字段而不仅仅是名称

http://ccrma.stanford.edu/planetccrma/man/man8/apt-cache.8.html

qbi也是正确的,你的正则表达式从一开始就有缺陷