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.*'