apt-get remove 删除的通配符比预期的多。为什么?

apt-get remove 删除的通配符比预期的多。为什么?

昨晚我试图刻录 CD。由于对 k3b 感到厌烦并选择使用 brasero,所以我决定删除 k3b。

我输入:

sudo apt-get remove k3b

我按了两次 Tab 键,发现我的系统上有 k3b 和 k3b-data。假设没有 k3b,我的系统上就不需要 k3b-data,所以我也想删除它,所以我输入了:

sudo apt-get remove k3b*

k3b不幸的是,我没有看就按了 Y 确认。它卸载了比和更多的软件包k3b-data。它卸载了不符合我的k3b*正则表达式的软件包。例如:transmissionnetwork-manager

k3b我相当确定and之间没有空格,*但我不知道为什么它会删除所有的内容。我对 apt-get 有什么误解吗?

答案1

您想要的命令是sudo apt-get remove '^k3b.*',因为:

  • 您需要.*匹配任意字符,任意次数
  • 您需要^匹配字符串的开头
  • 您需要引用正则表达式以防止 bash 将其解释*为通配符

(此答案补充并总结了 qbi 和 Flimm 先前提供的信息)

答案2

正则表达式*代表零个或任意多个。因此,您被告知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.

答案3

改用sudo apt-get remove ^k3b当您安装或删除软件包时,*通常是危险的,而且很少需要。如果您确实使用*,则应该引用它,但这样做不是使其更安全,因为它倾向于选择比你预期更多的包,这是由它的方式aptapt-get解释方式造成的,不是效果路径名扩展

  • 甚至安全使用*通常是不必要的
  • 不安全用途残酷. 删除将k3b*删除所有包含k3 任何地方在其名称中(以及依赖于此类包的每个包)。这不是拼写错误 - 包含k3就足够了,即使没有b,因为b*表示“零个或多个b”。

当你跑步时apt或者apt-get使用installremovepurge操作时,每个后续参数都是第一个1解释为单个包的名称。如果存在具有该名称的包,则将对其执行操作。

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

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

  • *允许前一项出现任意次数——包括仅一次或根本不发生——而不是恰好一次。
  • ?使前一项选修的——也就是说,允许它出现零次或一次。

apt-get(8)man apt-get)表示:

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

手册页仅提到.?*,但是它不完整,因为,,,,+和也足以让或将模式解释为正则表达式。|[^$apt-getapt3

.*尽管你可以用--匹配任意数量的任意字符不是只是*——你只需要它出现在中间你的正则表达式。因为该模式与包名称的任何子字符串匹配,所以它在模式的末尾(或开头)是没有意义的。

手册页提到^$. 这些(尤其是^)是编写用于installremove、 或中purge的操作的安全、高效模式的关键。aptapt-get

  • ^将正则表达式锚定到开始整个字符串。^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)可以被识别,并且 (二)出现在结尾参数,否则将被视为执行操作的包名称,可用于改变所执行的操作(例如,sudo apt install ubuntu-desktop^安装任务而不是包,并且当^出现在末尾时)。

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

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

答案4

使用 .* 代替 *,并放在引号内 ' '

sudo apt-get remove 'k3b.*'

相关内容