apt-get remove dengan wildcard dihapus jauh lebih dari yang diharapkan. Mengapa?

38

Tadi malam saya mencoba membakar CD. Karena kesal dengan k3b dan memilih untuk menggunakan brasero, saya pergi untuk menghapus k3b.

Saya mengetik:

sudo apt-get remove k3b

Saya menekan tab dua kali dan melihat bahwa saya memiliki data k3b dan k3b pada sistem saya. Dengan asumsi bahwa saya tidak akan memerlukan data-k3b pada sistem saya tanpa k3b, saya ingin menghapusnya juga jadi saya mengetik:

sudo apt-get remove k3b*

Sayangnya saya menekan Y untuk mengkonfirmasi tanpa melihat. Ini menghapus lebih dari k3bdan k3b-data. Itu menghapus paket yang tidak sesuai dengan k3b*regex saya . Misalnya: transmissiondan network-manager.

Saya cukup yakin bahwa saya tidak memiliki ruang di antara k3bdan *tapi saya tidak tahu mengapa lagi itu akan menghapus semua yang dilakukannya. Apakah ada sesuatu tentang apt-get yang saya salah pahami?

Steve Goykovich
sumber

Jawaban:

38

Perintah yang Anda inginkan adalah sudo apt-get remove '^k3b.*', karena:

  • Anda harus .*mencocokkan karakter apa pun, berapa kali
  • Anda harus ^mencocokkan awal string
  • Anda perlu mengutip regex untuk mencegah bash menginterpretasikan *sebagai wildcard

(Jawaban ini melengkapi dan merangkum info sebelumnya yang diberikan oleh qbi dan Flimm)

Boris Dalstein
sumber
5
Ini aman dan tidak apa-apa untuk menggunakannya tetapi Anda tidak memerlukannya .*. Anda bisa menggunakannya sudo apt-get remove ^k3b. Kehadiran ^cukup untuk menyebabkan argumen ditafsirkan sebagai ekspresi reguler, dan ketika aptatau apt-getmenafsirkan argumen sebagai ekspresi reguler, itu cocok dengan itu di mana saja dalam nama paket. Itu sebabnya Anda perlu ^-to jangkar pertandingan ke awal nama paket. Ekspresi reguler tidak perlu cocok dengan seluruh nama paket, sembarang bagian dari itu.
Eliah Kagan
1
@EliahKagan Thx untuk info tambahan! (dan memang, masuk akal bahwa jika Anda perlu ^, maka Anda tidak perlu .*)
Boris Dalstein
30

Ekspresi reguler *adalah nol atau banyak sembarang. Jadi Anda diberitahu apt-getuntuk menghapus apa pun yang berisi k3diikuti oleh sejumlah b, jadi pada dasarnya semua yang berisi k3. Jika saya mencoba perintah Anda di sistem saya, ia ingin menghapus 58 paket.

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.
qbi
sumber
huh! Saya sudah terjebak bekerja pada mesin windows sialan ini (di mana * hanya berarti "dan apa pun setelah") terlalu lama!
Steve Goykovich
14
Itu *bekerja sebagai wildcard untuk bash seperti di DOS, tetapi beberapa perintah seperti apt-getmengharapkan regex. Saat Anda mengetik sudo apt-get remove -s k3b*, bash pertama-tama akan mencari file apa pun di direktori Anda saat ini yang dimulai dengan k3b. Jika ditemukan, itu akan menggantikan argumen itu dengan nama file itu. Jika tidak, itu akan diteruskan k3b*langsung ke apt-get, yang akan menafsirkannya sebagai regex. Jika Anda tidak ingin bash menginterpretasikan asterisk sebagai wildcard terlebih dahulu (yang mungkin tidak Anda lakukan), tutup argumen dengan tanda kutip tunggal, seperti ini:sudo apt-get remove -s 'k3b*'
Flimm
3
Jadi perintah yang dimaksud seharusnya sudo apt-get remove -s 'k3b.*'. Baru saja menemukan jawaban ini dan merasa sangat penting untuk mengetahuinya. IMHO ini cukup tak terduga dan saya akan menandainya sebagai bug "perilaku tak terduga" apt-get ... Anda biasanya mengharapkan arti "glob" dan bukan makna "regexp" jika tidak ditentukan. Terima kasih dan +1!
Rmano
1
Dan untuk orang-orang seperti saya yang tidak tahu: -sopsinya berarti "simulasi". Ia memberi tahu apt-getuntuk tidak melakukan operasi, tetapi hanya untuk memberi tahu Anda tentang apa yang akan terjadi tanpa -sopsi.
Boris Dalstein
Saya pikir bahwa penggunaan tanda kutip tunggal untuk membuat globbing TIDAK bekerja, setidaknya dalam wayang. Dan itu tidak terduga. Dalam program 'find', jika saya menulis find / -iname 'project *' Saya akan menemukan semua yang dimulai dengan proyek, bukan sesuatu yang memiliki 'proyek' di dalamnya dan apa pun setelahnya. Sebagai bukti tentang boneka, perhatikan bagaimana hasil saya mengatakan 'regex', dan hasilnya membuktikannya?
Dennis
9

Gunakan sudo apt-get remove ^k3bsebagai gantinya. Ketika Anda menginstal atau menghapus paket, *seringkali berbahaya dan jarang dibutuhkan. Jika Anda menggunakannya *, Anda harus mengutipnya, tetapi itu tidak membuatnya lebih aman, karena kecenderungannya untuk memilih paket yang jauh lebih banyak daripada yang Anda inginkan adalah hasil dari cara aptdan apt-getmenafsirkannya dan bukan efek dari ekspansi pathname .

  • Bahkan penggunaan yang aman dari* yang sering tidak perlu .
  • Penggunaan yang tidak aman itu brutal . Menghapus k3b*Menghapus setiap paket yang berisi k3 mana saja dalam namanya (dan setiap paket yang tergantung pada paket tersebut). Itu bukan salah cetak yang k3cukup, bahkan tanpa b, karena b*berarti "nol atau lebih b."

Ketika Anda menjalankan aptatau apt-getdengan install, removeatau purgetindakan, setiap argumen berikutnya adalah pertama 1 ditafsirkan sebagai nama paket individu. Jika paket dengan nama persis itu ada, tindakan dilakukan untuk itu.

Jika tidak ada paket seperti itu, aptdan apt-getakan memeriksa apakah argumen mengandung salah satu umum ekspresi reguler metakarakter 2 . , ?, +,* , |, \[, ^, atau$ . Jika tidak, sudah selesai - tidak ada paket yang ditemukan.

Jika memang mengandung salah satu karakter tersebut, maka itu diperlakukan sebagai ekspresi reguler dan cocok dengan bagian mana pun dari nama paket apa pun. Itu tidak harus cocok dengan seluruh nama. Seperti yang dikatakan orang lain, *dalam ekspresi reguler tidak berarti sama dengan *di bola. ?juga tidak. Dalam ekspresi reguler:

  • *memungkinkan item sebelumnya muncul beberapa kali - termasuk hanya sekali atau tidak sama sekali - bukannya tepat sekali.
  • ?menjadikan item sebelumnya opsional --yaitu, memungkinkan item muncul nol atau satu kali.

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

Jika tidak ada paket yang cocok dengan ekspresi yang diberikan dan ekspresi berisi salah satu dari '.', '?' atau '*' kemudian diasumsikan sebagai ekspresi reguler POSIX, dan itu diterapkan ke semua nama paket dalam database. Semua kecocokan kemudian diinstal (atau dihapus). Perhatikan bahwa pencocokan dilakukan dengan substring sehingga 'lo. *' Cocok 'how-lo' dan 'terendah'. Jika ini tidak diinginkan, jangkar ekspresi reguler dengan karakter '^' atau '$', atau buat ekspresi reguler yang lebih spesifik.

Manual ini hanya menyebutkan ., ?, dan *, tapi itu tidak lengkap , seperti +, |, [, ^, dan $juga cukup untuk membiarkan apt-getatau aptmenafsirkan pola sebagai ekspresi reguler. 3

Meskipun Anda dapat mencocokkan sejumlah karakter apa pun dengan .*- bukan hanya - Anda *hanya memerlukan ini jika itu akan muncul di tengah ekspresi reguler Anda. Karena polanya cocok dengan substring apa pun dari nama paket, itu tidak ada gunanya di akhir (atau awal) dari pola.

Halaman manual menyebutkan ^dan$ . Ini (terutama ^) adalah kunci untuk menulis yang aman, pola efisien untuk digunakan dengan install, removeatau purgetindakan dalam aptatau apt-get.

  • ^jangkar ekspresi reguler ke awal seluruh string. ^k3bmemilih semua paket yang namanya dimulai dengan k3b.
  • $jangkar ekspresi reguler ke akhir seluruh string. k3b$akan memilih semua paket yang namanya diakhiri dengan k3b.

Karena itu Anda dapat menggunakan perintah ini untuk menghapus paket-paket dengan aman:

sudo apt-get remove ^k3b

Akhirnya, dalam kasus spesifik yang Anda sebutkan, Anda mungkin hanya perlu menyampaikan kedua nama itu sendiri:

sudo apt-get remove k3b k3b-data

Maka Anda menghindari semua kerumitan ini! (Meskipun jangkar dengan ^sederhana setelah Anda terbiasa.) Atau gunakan ekspansi brace , yang shell Anda ekspansi ke perintah di atas:

sudo apt-get remove k3b{,-data}

1 Ada dua pengecualian untuk ini: (a) beberapa pilihan (misalnya, -f, --purge) diakui, dan (b) beberapa karakter tanda baca muncul pada akhir dari argumen yang seharusnya dapat diambil sebagai nama paket untuk melakukan tindakan dapat digunakan untuk mengubah apa yang dilakukan (misalnya, sudo apt install ubuntu-desktop^menginstal tugas daripada paket, dan kapan ^muncul di akhir).

2 Metakarakter ekspresi reguler lainnya ada. Misalnya, \didukung oleh semua dialek ekspresi reguler dan yang umum digunakan. ., ?, +, *, |, [, ^, Dan $hanya terjadi untuk menjadi metakarakter pengembang APT memutuskan akan memicu interpretasi sebagai ekspresi reguler (setelah resolusi sebagai paket yang tepat bernama telah gagal).

3 Cara termudah untuk memverifikasi ini adalah dengan mensimulasikan pemasangan atau penghapusan dengan pola seperti itu, menggunakan -sopsi seperti dijelaskan di atas. Misalnya, menjalankan apt -s install ^virtualboxpertunjukan yang sudo apt install ^virtualboxakan berdampak mencoba menginstal setiap paket yang diketahui oleh manajer paket tentang siapa yang namanya dimulai virtualbox. Namun, perilaku ini juga dapat diverifikasi dengan memeriksa kode sumber . Periksa CacheSetHelper::PackageFromRegExfungsi di cacheset.cc.

Eliah Kagan
sumber
1

Anda lebih mungkin menghapus lib yang memiliki k3b di dalamnya yang menjadi sandaran program-program tersebut.

Singkatnya, Anda mungkin tidak pernah tahu. Saya sarankan tidak menggunakan wildcard untuk menghapus sesuatu dan membaca hal-hal ketika diminta (maaf).

Juga tanpa pencarian -n regex gunakan semua bidang dan bukan hanya nama

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

qbi juga benar regex Anda cacat sejak awal

kapas
sumber
Satu hal lagi, dalam kasus seperti milik Anda (data k3b dan k3b), apt-get uninstall k3b. Apt kemudian akan memberi tahu Anda jika Anda telah menginstal sesuatu yang tidak lagi Anda perlukan, dan apa yang perlu Anda lakukan untuk menghapusnya.
coteyr
Wow! Saya tidak akan pernah berharap untuk mencari dalam deskripsi juga! ya, ini pasti sesuatu yang tidak akan pernah saya lakukan lagi! (Dan saya akan pastikan untuk membaca hal-hal lain kali: P)
Steve Goykovich
Tautan terputus, maukah Anda menjelaskan bagaimana menggunakan -n?
Seanny123
-n berarti hanya mencari di bidang nama.
coteyr
Setelah mencoba, opsi -n tidak dikenali oleh apt-get remove, hanya oleh apt-get cache. Tampaknya sebenarnya, apt-get removehanya mencari nama paket, bukan deskripsi.
Boris Dalstein