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


38

Минулої ночі я намагався записати компакт-диски. Роздратований k3b і вибравши використовувати brasero замість цього, я пішов видалити k3b.

Я набрав:

sudo apt-get remove k3b

Я натиснув вкладку двічі і побачив, що у мене в системі є і 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 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.

тьфу! Я занадто довго затримався, працюючи над цими проклятими машинами для вікон (де * просто означає «і все, що завгодно»)!
Стів Гойкович

14
*Робить роботу в якості шаблону для Баша , як в DOS, але деякі команди типу apt-getочікують регулярне вираження. Під час введення sudo apt-get remove -s k3b*, bash спочатку шукатиме будь-які файли у вашому поточному каталозі, які починаються з k3b. Якщо він знайде який-небудь, він замінить цей аргумент тими іменами. Якщо ні, то він перейде k3b*безпосередньо до apt-get, що трактуватиме це як регулярний вираз. Якщо ви не хочете Баш інтерпретувати зірочку як груповий символ першого (який ви , ймовірно , немає), оточувати аргумент в одинарні лапки, як це:sudo apt-get remove -s 'k3b*'
Флімм

3
Отже, призначена команда була б sudo apt-get remove -s 'k3b.*'. Просто натрапили на цю відповідь і вважаєте, що це дійсно важливо знати. IMHO це зовсім несподівано, і я б цілком відзначив це помилкою apt-get "несподіваною поведінкою" ... ти зазвичай очікуєш значення "glob", а не значення "regexp", якщо не вказане. Все одно дякую та +1!
Рмано

1
І для таких, як я, хто не знав: -sваріант означає "моделювання". Це повідомляє apt-getне виконувати операцію, а просто інформувати вас про те, що буде без -sваріанту.
Борис Дальштейн

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

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

Ви, швидше за все, видалите lib, в якому був k3b, від якого залежали ці програми.

Словом, ви, можливо, ніколи не дізнаєтесь. Я рекомендую не використовувати підстановку для видалення речей та для читання речей, коли буде запропоновано (вибачте).

Крім того, для пошуку -n regex використовують усі поля, а не лише імена

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

також qbi правильний, що ваш регулярний вираз помиляється з початку роботи


Ще одна річ: у таких випадках, як ваш (дані k3b та k3b) просто apt - вилучіть k3b. Тоді Apt повідомить вас, якщо у вас встановлені речі, які вам більше не потрібні, і що вам потрібно зробити, щоб їх видалити.
coteyr

Оце Так! Я ніколи не очікував, що це також буде шукати в описах! так, це, безумовно, те, що я більше ніколи не зроблю! (і я обов’язково прочитаю речі наступного разу: 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.