apt-get remove与通配符删除的方式超出了预期。为什么?


38

昨晚我试图刻录CD。厌倦了k3b并选择使用brasero,我去掉了k3b。

我输入:

sudo apt-get remove k3b

我两次按下tab键,发现我的系统上同时具有k3b和k3b数据。假设没有k3b,我的系统上不需要k3b数据,我也想删除它,因此输入:

sudo apt-get remove k3b*

不幸的是,我打Y确认没有看。它卸载了一大堆不止k3bk3b-data。它卸载了不适合我的k3b*正则表达式的软件包。例如:transmissionnetwork-manager

我相当确定我k3b和之间没有空格,*但是我不知道为什么还要删除它所做的所有事情。我误会了apt-get吗?


Answers:


38

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

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

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


5
这是安全的,可以使用它,但是您不需要.*。您可以使用sudo apt-get remove ^k3b。存在^足以导致将参数解释为正则表达式,并且当aptapt-get将参数解释为正则表达式时,它将在程序包名称中的任何位置将其匹配。这就是为什么需要^- 将匹配项锚定到包名称的开头。正则表达式不需要匹配整个程序包名称,只需匹配其中的任何部分。
伊莱亚·卡根

1
@EliahKagan Thx了解更多信息!(实际上,这是有道理的,如果你需要^,那么你不需要.*
鲍里斯达尔斯坦

30

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

啊!我一直在这些织补Windows机器(其中*表示“及之后的任何东西”)上工作太久了!
史蒂夫·高科维奇

14
*做的工作,作为像DOS庆典通配符,但某些命令喜欢apt-get期待一个正则表达式。键入时sudo apt-get remove -s k3b*,bash会首先在当前目录中查找以开头的任何文件k3b。如果找到,它将用那些文件名替换该参数。如果不是,它将k3b*直接传递给apt-get,它将解释为正则表达式。如果您不希望bash首先将星号解释为通配符(您可能不希望这样做),则将参数用单引号引起来,如下所示:sudo apt-get remove -s 'k3b*'
Flimm 2012年

3
因此,预期的命令应该是sudo apt-get remove -s 'k3b.*'。刚刚偶然发现了这个答案,发现它真的很重要。恕我直言,这是非常出乎意料的,我会把它标记为apt-get的“意外行为”错误...您通常期望的是“ glob”的意思,如果没有指定,则不是“ regexp”的意思。无论如何还是谢谢+1!
Rmano 2014年

1
对于像我这样不知道的人:该-s选项表示“模拟”。它告诉您apt-get不要执行该操作,而只是告诉您没有该-s选项会发生什么情况。
鲍里斯·达尔斯泰因

我认为您至少在人偶中使用单引号来创建通配符无效。那 出乎意料的。在'find'程序中,如果我写find / -iname'project *',我将找到以project开头的所有内容,而不是其中包含“ project”的内容以及之后的任何内容。作为有关木偶的证据,请注意我的结果怎么说“ regex”,结果证明了这一点?
丹尼斯2015年

9

使用sudo apt-get remove ^k3b代替。当您安装或删除软件包时,*通常很危险,几乎不需要。如果你使用*,你应该引用它,但是这并不能使其更安全,因为比你想要的方式的结果的倾向来选择更为封装aptapt-get解析它并没有的效果路径扩展

  • 甚至安全使用*常常是不必要的
  • 不安全的使用是残酷的。删除k3b*将删除名称中包含k3 任何位置的每个程序包(以及依赖于该程序包的每个程序包)。这不是一个错字k3,即使没有,也包含在内就足够了b,因为它b*表示“零或多个bs”。

当运行aptapt-getinstallremovepurge动作,每个后续参数是第一1解释为个别包的名称。如果存在具有该确切名称的软件包,则将对其执行操作。

如果不存在这样的包,apt并且apt-get将检查参数包含任何常见的正则表达式 元字符2 .?+*|\[^,或$。如果没有,那就完成了-没有找到软件包。

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

  • *允许前一项显示任意次数-包括一次或完全不显示-而不是一次。
  • ?将前一项设为可选 -也就是说,它允许它出现零次或一次。

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

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

手册页只提到.?*,但它是不完全的,如+|[^,和$也足以让apt-getapt解释图案作为正则表达式。3

虽然可以匹配任何数量的任何字符.*- 只是*-您只需要这个,如果它会出现在中间的正则表达式。由于该模式与程序包名称的任何子字符串匹配,因此在模式的结尾(或开头)毫无意义。

该联机帮助页中提到^$。这些(尤其是^)的关键是编写安全,高效的方式与使用installremove或者purge在行动aptapt-get

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

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

sudo apt-get remove ^k3b

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

sudo apt-get remove k3b k3b-data

这样您就可以避免所有这些复杂性!(虽然使用起来^很简单,但是锚定很简单。)或者使用brace expand,它会将您的shell扩展为上述命令:

sudo apt-get remove k3b{,-data}

1 有两个例外:(a)中的一些选项(例如,-f--purge)被识别,和 (b)中出现在某些标点字符结束,否则将被认为是包的名称以执行动作可以是一个参数的用于更改已完成的操作(例如,sudo apt install ubuntu-desktop^安装任务而不是软件包,以及何时^显示在末尾)。

2 存在其他正则表达式元字符。例如,\正则表达式的所有方言都支持和常用。.?+*|[^,并且$恰好是元字符的APT开发商决定将触发解释为正则表达式(如命名一个确切的封装解决方案后已失败)。

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


1

然后,您很可能会删除其中包含那些程序所依赖的k3b的库。

简而言之,您可能永远不知道。我建议不要使用通配符删除内容并在出现提示时阅读内容(对不起)。

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

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

也qbi是正确的,您的正则表达式从一开始就存在缺陷


另一件事,在像您这样的情况下(k3b和k3b数据),可以轻松地卸载k3b。然后,Apt会通知您是否已安装不再需要的东西,以及删除它们所需执行的操作。
coteyr 2012年

哇!我也没想到它也可以在描述中搜索!是的,这绝对是我永远不会再做的事情!(下次我一定会读的书:P)
史蒂夫·高科维奇

链接已断开,您是否想弄清楚如何使用-n?
Seanny123 2013年

-n表示仅在名称字段中搜索。
coteyr

尝试后,-n选项不能被识别apt-get remove,只能被识别apt-get cache。看来,实际上,它apt-get remove仅查找程序包名称,而不是描述。
鲍里斯·达尔斯泰因
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.