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


38

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

Я набрал:

sudo apt-get remove k3b

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

sudo apt-get remove k3b*

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

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


Ответы:


38

Команда, которую вы хотите sudo apt-get remove '^k3b.*' , потому что:

  • Тебе нужно .* соответствовать любому персонажу, любое количество раз
  • Тебе нужно ^ соответствовать началу строки
  • Вы должны процитировать регулярное выражение для предотвращения интерпретации bash * как подстановочный знак

(Этот ответ завершает и суммирует предыдущую информацию, предоставленную qbi и Flimm)


5
Это безопасно, и это нормально использовать, но вам не нужно .*. Вы можете просто использовать sudo apt-get remove ^k3b. Наличие ^достаточно для того, чтобы аргумент интерпретировался как регулярное выражение, и когда aptили apt-getинтерпретирует аргумент как регулярное выражение, он совпадает с ним в любом месте имени пакета. Вот почему вам нужно ^- привязать совпадение к началу имени пакета. Регулярное выражение не должно совпадать с полным именем пакета, только с любой его частью.
Элия ​​Каган

1
@EliahKagan Спасибо за дополнительную информацию! (и действительно, имеет смысл, что если вам нужно ^, то вам и не нужно .*)
Борис

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
Это *работает как подстановочный знак для bash, как в DOS, но некоторые команды, например, apt-getожидают регулярное выражение. Когда вы печатаете sudo apt-get remove -s k3b*, bash сначала будет искать любые файлы в вашем текущем каталоге, которые начинаются с k3b. Если он найдет их, он заменит этот аргумент этими именами файлов. Если нет, он перейдет k3b*непосредственно к apt-get, что будет интерпретировать его как регулярное выражение. Если вы не хотите, чтобы bash сначала интерпретировал звездочку как подстановочный знак (чего, вероятно, нет), sudo apt-get remove -s 'k3b*'
заключите

3
Таким образом, предполагаемая команда была бы sudo apt-get remove -s 'k3b.*'. Просто наткнулся на этот ответ и считаю действительно важным знать. ИМХО, это довольно неожиданно, и я бы совершенно отметил это как «неожиданное поведение» ошибки apt-get ... вы обычно ожидаете значение «glob», а не «regexp», если оно не указано. В любом случае спасибо и +1!
Rmano

1
И для таких, как я, кто не знал: -sопция означает «симуляция». Он говорит apt-getне выполнять операцию, а просто информировать вас о том, что произойдет без -sопции.
Борис Дальштейн

Я думаю, что использование одиночных кавычек для создания глобализации НЕ работает, по крайней мере, в марионетках. И это является неожиданным. В программе 'find', если я напишу find / -iname 'project *', я найду все, что начинается с проекта, а не то, в котором есть 'project', и что-нибудь после него. В качестве доказательства, касающегося кукол, обратите внимание, как мои результаты говорят «регулярное выражение», и результаты подтверждают это?
Деннис

9

использование sudo apt-get remove ^k3b вместо этого. Когда вы устанавливаете или удаляете пакеты, *это часто опасно и редко требуется. Если вы используете *, вы должны заключить его в кавычки, но это не делает его более безопасным, потому что его тенденция выбирать гораздо больше пакетов, чем вы предполагаете, является результатом способа aptи apt-getинтерпретировать его, а не эффект расширения имени пути .

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

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

Если такого пакета нет 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) признаются, и (б) некоторые знаки пунктуации , появляющиеся в конце аргумента , которые иначе были бы приняты в качестве имени пакета , чтобы выполнить действие , может быть используется для изменения того, что сделано (например, sudo apt install ubuntu-desktop^устанавливает задачу, а не пакет, и когда ^появляется в конце).

2 Существуют и другие метасимволы регулярных выражений. Например, \поддерживается все диалекты регулярных выражений и часто используются. ., ?, +, *, |, [, ^, И$ просто оказались метасимволами метких разработчики решили бы вызвать интерпретацию как регулярное выражение (после разрешения в качестве точного пакета с именем не удался).

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) просто apt-get uninstall k3b. Затем Apt сообщит вам, если у вас установлены вещи, которые вам больше не нужны, и что вам нужно сделать, чтобы удалить их.
Котейр

Вот Это Да! Я никогда не ожидал бы, что это будет искать в описаниях тоже! да, это определенно то, что я никогда больше не сделаю! (и я обязательно прочитаю вещи в следующий раз: P)
Стив Гойкович

Ссылка не работает, не могли бы вы уточнить, как использовать -n?
Seanny123

-n означает только поиск в поле имен.
Coteyr

После попытки опция -n не распознается apt-get remove, только apt-get cache. Кажется, что на самом деле, apt-get removeищет только имена пакетов, а не описания.
Борис Дальштейн
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.