apt-get remove z usuniętym znakiem zastępczym znacznie więcej niż oczekiwano. czemu?


38

Ostatniej nocy próbowałem nagrać płyty CD. Rozzłościło mnie k3b i zamiast tego zdecydowałem się na brasero, więc postanowiłem usunąć k3b.

Wpisałem:

sudo apt-get remove k3b

Nacisnąłem klawisz Tab dwa razy i zobaczyłem, że mam zarówno dane k3b, jak i k3b w moim systemie. Zakładając, że nie potrzebowałbym danych k3b w moim systemie bez k3b, chciałem je również usunąć, więc wpisałem:

sudo apt-get remove k3b*

Niestety uderzyłem Y, żeby potwierdzić, nie patrząc. Odinstalował o wiele więcej niż k3bi k3b-data. Odinstalował pakiety, które nie pasowały do ​​mojego k3b*wyrażenia regularnego. Na przykład: transmissioni network-manager.

Jestem prawie pewna, że nie ma przestrzeni między k3bi *, ale nie wiem dlaczego jeszcze byłoby usunąć wszystko, co zrobił. Czy jest coś w apt-get, czego nie rozumiem?


Odpowiedzi:


38

Polecenie, które chcesz sudo apt-get remove '^k3b.*', ponieważ:

  • Musisz .*dopasować dowolną postać, dowolną liczbę razy
  • Musisz ^dopasować początek łańcucha
  • Musisz zacytować wyrażenie regularne, aby zapobiec interpretacji przez bash znaku *zastępczego

(Ta odpowiedź uzupełnia i podsumowuje poprzednie informacje dostarczone przez qbi i Flimm)


5
Jest to bezpieczne i można z niego korzystać, ale nie potrzebujesz .*. Możesz po prostu użyć sudo apt-get remove ^k3b. Obecność ^argumentu wystarcza, aby argument został zinterpretowany jako wyrażenie regularne, a gdy aptlub apt-getinterpretuje argument jako wyrażenie regularne, dopasowuje go w dowolnym miejscu w nazwie pakietu. Dlatego potrzebujesz ^- do zakotwiczenia dopasowania na początku nazwy pakietu. Wyrażenie regularne nie musi pasować do całej nazwy pakietu, tylko do dowolnej jego części.
Eliah Kagan

1
@EliahKagan Thx, aby uzyskać dodatkowe informacje! (i rzeczywiście ma sens, że jeśli potrzebujesz ^, to nie potrzebujesz .*)
Boris Dalstein,

30

Wyrażenie regularne *oznacza zero lub dowolnie wiele. Więc kazałeś apt-getusunąć wszystko, co zawiera, k3a następnie dowolną liczbę b, więc w zasadzie wszystko, co zawiera k3. Jeśli spróbuję wykonać polecenie w moim systemie, chce usunąć 58 pakietów.

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.

fuj! Utknąłem pracując nad tymi cholernymi maszynami do okien (gdzie * oznacza po prostu „i wszystko po”) o wiele za długo!
Steve Goykovich

14
*Działa jako zamiennika dowolnego ciągu bash jak w DOS, ale niektóre polecenia podoba apt-getoczekiwać regex. Podczas pisania sudo apt-get remove -s k3b*, bash najpierw szuka plików w bieżącym katalogu, które zaczynają się od k3b. Jeśli znajdzie jakiś, zastąpi ten argument tymi nazwami plików. Jeśli nie, przejdzie k3b*bezpośrednio do apt-get, co zinterpretuje to jako wyrażenie regularne. Jeśli nie chcesz, aby bash zinterpretował gwiazdkę jako symbol wieloznaczny jako pierwszy (czego prawdopodobnie nie masz), otoczyć argument pojedynczymi cudzysłowami, jak poniżej:sudo apt-get remove -s 'k3b*'
Flimm 12.12. O

3
Tak byłoby zamierzone polecenie sudo apt-get remove -s 'k3b.*'. Natknąłem się na tę odpowiedź i uważam, że to naprawdę ważne, aby wiedzieć. IMHO jest to dość nieoczekiwane i naznaczyłbym to jako błąd „nieoczekiwanego zachowania” apt-get ... zwykle oczekujesz znaczenia „glob”, a nie „regexp”, jeśli nie zostanie określone. W każdym razie dzięki i +1!
Rmano,

1
A dla takich jak ja, którzy nie wiedzieli: ta -sopcja oznacza „symulację”. Mówi, apt-getaby nie wykonywać operacji, ale po prostu informować o tym, co by się stało bez -sopcji.
Boris Dalstein,

Myślę, że użycie pojedynczych cudzysłowów do tworzenia globowania NIE działa, przynajmniej w marionetce. I to jest nieoczekiwane. W programie „znajdź”, jeśli napiszę projekt find / -iname * *, znajdę wszystko, co zaczyna się od projektu, a nie coś, co zawiera „projekt” i wszystko po nim. Jako dowód dotyczący marionetki zauważ, jak moje wyniki mówią „regex”, a wyniki to potwierdzają?
Dennis

9

Użyj sudo apt-get remove ^k3bzamiast tego. Podczas instalowania lub usuwania pakietów *jest często niebezpieczny i rzadko potrzebny. Jeśli używasz *, powinieneś go zacytować, ale to nie czyni go bezpieczniejszym, ponieważ jego tendencja do wybierania znacznie większej liczby pakietów, niż zamierzasz, jest wynikiem sposobu apti apt-getinterpretacji, a nie efektem rozwijania nazwy ścieżki .

  • Nawet bezpieczne zastosowania*często niepotrzebne .
  • Niebezpieczne zastosowania są brutalne . Usunięcie k3b*usuwa każdy pakiet, który zawiera k3 dowolne miejsce w jego nazwie (i każdy pakiet, który zależy od takiego pakietu). To nie jest literówka - zawieranie k3jest wystarczające, nawet bez b, ponieważ b*oznacza „zero lub więcej bs”.

Po uruchomieniu aptlub apt-getz install, removelub purgedziałania, każdy kolejny argument to pierwszy 1 interpretowane jako nazwa opakowaniu jednostkowym. Jeśli istnieje pakiet o tej dokładnej nazwie, wykonywana jest dla niego akcja.

Jeśli nie ma takiego pakietu, apti apt-getsprawdzi, czy argument zawiera którekolwiek z typowych wyrażeń regularnych metaznaki 2 . , ?, +,* , |, \[, ^, lub$ . Jeśli nie, to gotowe - nie znaleziono pakietu.

Jeśli nie zawierają żadnego z tych znaków, to jest traktowane jako wyrażenie regularne i porównywana z jakiejkolwiek części jakiejkolwiek nazwy pakietu. Nie musi pasować do całej nazwy. Jak powiedzieli inni, *wyrażenie regularne nie oznacza tego samego, co *glob. ?też nie. W wyrażeniu regularnym:

  • *pozwala, aby poprzedni element pojawiał się dowolną liczbę razy - w tym tylko raz lub wcale - zamiast dokładnie raz.
  • ?sprawia, że ​​poprzedni element jest opcjonalny - to znaczy, że może pojawić się zero lub jeden raz.

apt-get (8) ( man apt-get) mówi:

Jeśli żaden pakiet nie pasuje do podanego wyrażenia, a wyrażenie zawiera jedno z „.”, „?” lub „*”, wówczas przyjmuje się, że jest to wyrażenie regularne POSIX i jest stosowane do wszystkich nazw pakietów w bazie danych. Wszelkie dopasowania są następnie instalowane (lub usuwane). Zauważ, że dopasowanie odbywa się przez podciąg, więc „lo. *” Dopasowuje „how-lo” i „najniższą”. Jeśli jest to niepożądane, zakotwicz wyrażenie regularne znakiem „^” lub „$” albo utwórz bardziej szczegółowe wyrażenie regularne.

Manpage tylko wspomina ., ?i *, ale jest niekompletna , jak +, |, [, ^, i $są również wystarczające, aby pozwolić apt-getlub aptzinterpretować jako wzorzec wyrażenia regularnego. 3)

Chociaż można dopasować dowolną ilość dowolnych znaków z .*- nie wystarczy *tylko --you to potrzebne, jeśli wydaje się w środku swojego wyrażenia regularnego. Ponieważ wzorzec jest dopasowywany do dowolnego podciągu nazwy pakietu, nie ma sensu na końcu (lub początku) wzorca.

Strona wspomina ^i$ . Tych (szczególnie ^) są kluczem do pisania bezpiecznych, skutecznych wzorców do użytku z install, removelub purgedziałania w aptlub apt-get.

  • ^zakotwicza wyrażenie regularne na początku całego łańcucha. ^k3bwybiera wszystkie pakiety, których nazwy zaczynają się k3b.
  • $zakotwicza wyrażenie regularne na końcu całego łańcucha. k3b$wybrałby wszystkie pakiety, których nazwy kończą się na k3b.

Dlatego możesz użyć tego polecenia, aby bezpiecznie usunąć pakiety:

sudo apt-get remove ^k3b

Wreszcie, w konkretnym przypadku, o którym wspomniałeś, równie dobrze możesz po prostu podać oba nazwiska:

sudo apt-get remove k3b k3b-data

Wtedy unikniesz całej tej złożoności! (Chociaż zakotwiczenie za pomocą ^jest proste, gdy już się do tego przyzwyczaisz). Lub użyj rozszerzenia nawiasów , które twoja powłoka rozwija do powyższego polecenia:

sudo apt-get remove k3b{,-data}

1 Istnieją dwa wyjątki to: (a) niektóre opcje (np -f, --purge) są rozpoznawane i (b) niektóre znaki interpunkcyjne pojawiające się na końcu argumentu, które byłyby uznawane za nazwę pakietu wykonywać działania mogą być służy do zmiany tego, co zostało zrobione (np. sudo apt install ubuntu-desktop^instaluje zadanie zamiast pakietu i kiedy ^pojawia się na końcu).

2 Istnieją inne metaznaki wyrażeń regularnych. Na przykład \jest obsługiwany przez wszystkie dialekty wyrażeń regularnych i powszechnie używane. ., ?, +, *, |, [, ^, I $po prostu stało się metaznaki apt deweloperzy zdecydowali spowodowałaby interpretację jako wyrażenie regularne (po ustąpieniu jako dokładnym pakiecie o nazwie nie udało).

3 Najłatwiejszym sposobem sprawdzenia tego jest symulacja instalacji lub usunięcia z takim wzorcem, przy użyciu -sopcji opisanej powyżej. Na przykład uruchamianie apt -s install ^virtualboxprogramów, sudo apt install ^virtualboxktóre skutkowałyby próbą zainstalowania każdego pakietu, o którym menedżer pakietów wie, od którego imienia zaczyna się nazwa virtualbox. To zachowanie można jednak również zweryfikować, sprawdzając kod źródłowy . Sprawdź CacheSetHelper::PackageFromRegExfunkcję w cacheset.cc.


1

Prawdopodobnie usuniesz bibliotekę zawierającą k3b, od której zależały te programy.

Krótko mówiąc, możesz nigdy nie wiedzieć. Odradzam używanie symboli wieloznacznych do usuwania rzeczy i czytania ich po wyświetleniu monitu (przepraszam).

Również bez opcji -n wyrażenia regularne używają wszystkich pól, a nie tylko nazw

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

również qbi jest poprawne, twoje wyrażenie regularne jest wadliwe od samego początku


Jeszcze jedno, w przypadkach takich jak twoje (dane k3b i k3b) po prostu apt-get odinstaluj k3b. Apt poinformuje Cię wtedy, jeśli masz zainstalowane rzeczy, których już nie potrzebujesz, i co musisz zrobić, aby je usunąć.
coteyr

łał! Nigdy bym się nie spodziewał, że przeszuka także opisy! tak, to zdecydowanie coś, czego nigdy więcej nie zrobię! (i będę
musiał

Link jest zepsuty, czy mógłbyś wyjaśnić, jak używać -n?
Seanny123 17.09.13

-n oznacza wyszukiwanie tylko w polu nazw.
coteyr

Po próbie opcja -n nie jest rozpoznawana przez apt-get remove, tylko przez apt-get cache. Wygląda na to, że tak naprawdę apt-get removeszuka tylko nazw pakietów, a nie opisów.
Boris Dalstein,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.