apt-get remove с удаленными подстановочными знаками намного больше, чем ожидалось. Зачем?

Прошлой ночью я пытался записать компакт-диски. Раздражая k3b и выбрав вместо этого brasero, я решил удалить k3b. Я набрал:

sudo apt-get remove k3b

Я дважды нажал на tab и увидел, что в моей системе есть как k3b, так и k3b-данные. Предполагая, что мне не нужны данные k3b в моей системе без k3b, я тоже хотел их удалить, поэтому набрал:

sudo apt-get remove k3b*

К сожалению, я нажал Y, чтобы подтвердить, не глядя. Он удалил намного больше, чем k3b и k3b-data. Он удалил пакеты, которые не подходили для моего регулярного выражения "k3b*". Например: передача и сетевой менеджер

Я вполне уверен, что у меня не было пробела между k3b и *, но я не знаю, почему иначе он удалил бы все, что сделал. Есть ли что-то в apt-get, что я неправильно понимаю?

4 ответа

Команда, которую вы хотите 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 интерпретировать это, а не эффект расширения пути.

  • Даже безопасное использование * часто не нужны.
  • Небезопасное использование жестоко. Удаление k3b* удаляет каждый пакет, который содержит k3 где-нибудь в его имени (и каждый пакет, который зависит от такого пакета). Это не опечатка, содержащая k3 достаточно даже без b, так как b* означает "ноль или более b s ".

Когда ты бежишь aptили же apt-get с install, remove, или же purge действие, каждый последующий аргумент сначала интерпретируется как имя отдельного пакета. Если пакет с таким точным именем существует, для него выполняется действие.

Если такой упаковки нет, apt а также apt-get проверит, содержит ли аргумент какой-либо из общих метасимволов регулярного выражения 2 ., ?, + , *, |, \[, ^ , или же $, Если нет, то сделано - пакет не найден.

Если он содержит какой-либо из этих символов, он обрабатывается как регулярное выражение и сопоставляется с любой частью любого имени пакета. Это не должно соответствовать целому имени. Как уже говорили другие, * в регулярном выражении не означает то же самое, что * в шар. ? тоже нет В регулярном выражении:

  • * позволяет предыдущему элементу появляться любое количество раз - включая только один раз или вообще не появляться - вместо ровно одного раза.
  • ? делает предыдущий элемент необязательным - то есть, он позволяет ему появляться ноль или один раз.

apt-get (8) (man apt-get) говорит:

Если ни один пакет не соответствует данному выражению, и выражение содержит один из '.', '?' или '*', тогда предполагается, что это регулярное выражение POSIX, и оно применяется ко всем именам пакетов в базе данных. Любые совпадения затем устанавливаются (или удаляются). Обратите внимание, что сопоставление выполняется с помощью подстроки, поэтому 'lo.*' Соответствует 'how-lo' и 'наименьшему' Если это нежелательно, закрепите регулярное выражение символом "^" или "$" или создайте более конкретное регулярное выражение.

Справочная страница только упоминает ., ?, а также *, но оно неполное, так как +, |, [, ^, а также $ также достаточно, чтобы позволить apt-get или же apt интерпретировать шаблон как регулярное выражение. 3

Хотя вы можете сопоставить любое количество любых символов с .* - не только * - вам нужно только это, если оно появится в середине вашего регулярного выражения. Поскольку шаблон сопоставляется с любой подстрокой имени пакета, он не имеет смысла в конце (или начале) шаблона.

Руководство упоминает ^ а также $, Эти (особенно ^) являются ключом к написанию безопасных, эффективных шаблонов для использования с install, remove, или же purge действия в apt или же apt-get,

  • ^ привязывает регулярное выражение к началу всей строки. ^k3b выбирает все пакеты, имена которых начинаются с k3b,
  • $ привязывает регулярное выражение к концу всей строки. k3b$ выбрал бы все пакеты, имена которых заканчиваются на k3b,

Поэтому вы можете использовать эту команду для безопасного удаления пакетов:

sudo apt-get remove ^k3b

Наконец, в конкретном случае, который вы упомянули, вы могли бы просто передать оба имени самостоятельно:

sudo apt-get remove k3b k3b-data

Тогда вы избежите всей этой сложности! (Хотя якорь с ^ Это просто, если вы привыкли к нему.) Или используйте расширение скобки, которое ваша оболочка раскрывает в приведенную выше команду:

sudo apt-get remove k3b{,-data}

1 Есть два исключения из этого: (а) некоторые варианты (например, -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 ,

Скорее всего, вы удалите библиотеку с k3b, от которой зависели эти программы.

Короче говоря, вы никогда не узнаете. Я рекомендую не использовать подстановочный знак, чтобы удалить что-либо и прочитать что-либо по запросу (извините).

Кроме того, при поиске без регулярного выражения -n используются все поля, а не только имена.

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

также Qbi правильно, ваше регулярное выражение имеет недостатки с самого начала

Ты можешь использовать apt searchкоторый имеет преимущество поиска как в именах пакетов, так и в описаниях пакетов, но это также немного опасно. например, если вы хотите удалить любой пакет, связанный с MY_PATTERN Вы можете запустить:

sudo apt search MY_PATTERN | grep "^[^\ ]*/" -o | sed 's/\///' | xargs -I '{}' sudo apt remove -y '{}'

БУДЬТЕ ОСТОРОЖНЫ: не используйте небольшие поисковые шаблоны, которые можно найти во многих словах, например he, and,.... это может привести к удалению несвязанного пакета и, следовательно, к повреждению. Перед запуском проверьте вывод apt search MY_PATTERN первый.

apt search MY_PATTERN: Найдите шаблон в именах пакетов и описаниях пакетов в удаленных репозиториях.

grep "^[^\ ]*/" -o: извлечь имя пакета.

sed 's/\///': удалять / из извлеченных имен.

xargs -I '{}' sudo apt remove -y '{}': удалить по одному.

Используйте.* Вместо * и заключите в кавычки ' '

sudo apt-get remove 'k3b.*'
Другие вопросы по тегам