Apt-Get entfernen mit Wildcard entfernt viel mehr als erwartet. Warum?

38

Letzte Nacht habe ich versucht, CDs zu brennen. Als ich mich über k3b ärgerte und stattdessen brasero auswählte, entfernte ich k3b.

Ich tippte ein:

sudo apt-get remove k3b

Ich drückte zweimal die Tabulatortaste und sah, dass ich sowohl k3b- als auch k3b-Daten auf meinem System hatte. Unter der Annahme, dass ich ohne k3b keine k3b-Daten auf meinem System benötige, wollte ich diese auch entfernen und gab Folgendes ein:

sudo apt-get remove k3b*

Leider drücke ich Y, um zu bestätigen, ohne zu schauen. Es hat viel mehr deinstalliert als k3bund k3b-data. Es deinstallierte Pakete, die nicht zu meinem k3b*regulären Ausdruck passten . Zum Beispiel: transmissionund network-manager.

Ich bin ziemlich sicher , dass ich nicht einen Raum zwischen habe k3bund , *aber ich weiß nicht , warum sonst würde es entfernen , dass es tut. Gibt es etwas an apt-get, das ich missverstehe?

Steve Goykovich
quelle

Antworten:

38

Der gewünschte Befehl lautet sudo apt-get remove '^k3b.*', weil:

  • Sie müssen .*mit jedem Zeichen übereinstimmen, und zwar beliebig oft
  • Sie müssen ^mit dem Anfang der Zeichenfolge übereinstimmen
  • Sie müssen den regulären Ausdruck in Anführungszeichen setzen, um zu verhindern, dass Bash *als Platzhalter interpretiert wird

(Diese Antwort vervollständigt und fasst die vorherigen Informationen von qbi und Flimm zusammen.)

Boris Dalstein
quelle
5
Dies ist sicher und es ist in Ordnung, es zu benutzen, aber Sie brauchen das nicht .*. Sie können nur verwenden sudo apt-get remove ^k3b. Das Vorhandensein von ^ausreichend ist , um zu bewirken , dass das Argument als regulärer Ausdruck interpretiert werden, und wenn aptoder apt-getinterpretiert ein Argument als regulären Ausdruck, sie paßt es überall in dem Paketnamen. Aus diesem Grund müssen Sie ^--den Treffer am Anfang des Paketnamens verankern . Der reguläre Ausdruck muss nicht mit dem gesamten Paketnamen übereinstimmen, sondern nur mit einem Teil davon.
Eliah Kagan
1
@EliahKagan Thx für die zusätzlichen Infos! (und in der Tat macht es Sinn, dass, wenn Sie brauchen ^, dann brauchen Sie nicht .*)
Boris Dalstein
30

Der reguläre Ausdruck *steht für Null oder beliebig viele. Also hast du gesagt apt-get, dass du alles entfernen sollst , was enthält, k3gefolgt von einer beliebigen Anzahl von b, also im Grunde alles, was enthält k3. Wenn ich Ihren Befehl auf meinem System ausprobiere, möchte es 58 Pakete entfernen.

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
quelle
Pfui! Ich habe viel zu lange an diesen verdammten Fenstermaschinen gearbeitet (wo * nur "und irgendetwas danach" bedeutet)!
Steve Goykovich
14
Das *funktioniert als Platzhalter für Bash wie in DOS, aber einige Befehle wie apt-geterwarten einen regulären Ausdruck. Bei der sudo apt-get remove -s k3b*Eingabe sucht bash zuerst nach allen Dateien in Ihrem aktuellen Verzeichnis, die mit beginnen k3b. Wenn es welche findet, wird es dieses Argument durch diese Dateinamen ersetzen. Wenn nicht, wird es k3b*direkt an übergeben apt-get, was es als regulären Ausdruck interpretiert. Wenn Sie nicht möchten, dass bash das Sternchen zuerst als Platzhalter interpretiert (was Sie wahrscheinlich nicht tun), setzen Sie das Argument in einfache Anführungszeichen:sudo apt-get remove -s 'k3b*'
Flimm,
3
Der beabsichtigte Befehl wäre also gewesen sudo apt-get remove -s 'k3b.*'. Bin nur auf diese Antwort gestoßen und finde es wirklich wichtig zu wissen. IMHO ist dies ziemlich unerwartet und ich würde es als "unerwartetes Verhalten" Fehler von apt-get markieren ... Sie erwarten normalerweise eine "glob" Bedeutung und keine "regexp" Bedeutung, wenn nicht angegeben. Trotzdem danke und +1!
Rmano
1
Und für diejenigen wie mich, die es nicht wussten: Die -sOption bedeutet "Simulation". Es wird angezeigt apt-get, die Operation nicht auszuführen, sondern Sie lediglich darüber zu informieren, was ohne die -sOption geschehen würde .
Boris Dalstein
Ich denke, dass Ihre Verwendung von einfachen Anführungszeichen, um Globbing zu erstellen, zumindest in Marionetten NICHT funktioniert. Und das ist unerwartet. Wenn ich im Programm 'find' find / -iname 'project *' schreibe, finde ich alles, was mit project beginnt, nicht etwas, in dem 'project' und nichts danach enthalten ist. Beachten Sie als Beweis für Marionette, wie meine Ergebnisse "Regex" sagen, und die Ergebnisse beweisen es?
Dennis
9

Verwenden Sie sudo apt-get remove ^k3bstattdessen. Wenn Sie Pakete installieren oder entfernen, *ist dies häufig gefährlich und wird selten benötigt. Wenn Sie es verwenden *, sollten Sie es zitieren, aber das macht es nicht sicherer, da seine Tendenz, weit mehr Pakete auszuwählen, als Sie beabsichtigen, das Ergebnis der Art aptund Weise und der apt-getInterpretation ist und keine Auswirkung der Pfadnamenerweiterung .

  • Auch sichere Verwendungen* sind oftmals nicht erforderlich .
  • Unsichere Verwendungen sind brutal . Durch das Entfernen k3b*wird jedes Paket entfernt, das k3 irgendwo in seinem Namen enthalten ist (und jedes Paket, das von einem solchen Paket abhängt). Das ist kein Tippfehler - k3es reicht aus, auch ohne das b, denn es b*bedeutet "null oder mehr bs".

Wenn Sie laufen aptoder apt-getmit dem install, removeoder purgeAction, jede nachfolgende Argument ist zunächst 1 als Name eines einzelnen Pakets interpretiert. Wenn ein Paket mit diesem genauen Namen vorhanden ist, wird die Aktion für dieses Paket ausgeführt.

Wenn es kein solches Paket, aptund apt-getprüft , ob das Argument eine der gemeinsamen enthält regulären Ausdruck Metazeichen 2 . , ?, +,* , |, \[, ^, oder$ . Wenn nicht, ist es geschafft - es wurde kein Paket gefunden.

Wenn es nicht eine dieser Zeichen enthält, dann wird er als regulärer Ausdruck behandelt und gegen abgestimmt jeden Teil eines Paketnamen. Es muss nicht mit dem ganzen Namen übereinstimmen. Wie andere gesagt haben, bedeutet *ein regulärer Ausdruck nicht dasselbe wie *ein Globus. ?tut es auch nicht. In einem regulären Ausdruck:

  • *Ermöglicht, dass das vorherige Element beliebig oft angezeigt wird - einschließlich nur einmal oder überhaupt nicht - und nicht genau einmal.
  • ?macht das vorherige Element optional - das heißt, es lässt zu, dass es null oder einmal erscheint.

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

Wenn kein Paket mit dem angegebenen Ausdruck übereinstimmt und der Ausdruck eines von '.', '?' Enthält oder '*' wird als regulärer POSIX-Ausdruck angenommen und auf alle Paketnamen in der Datenbank angewendet. Alle Übereinstimmungen werden dann installiert (oder entfernt). Beachten Sie, dass der Abgleich durch einen Teilstring erfolgt, sodass "lo. *" Mit "how-lo" und "low" übereinstimmt. Wenn dies unerwünscht ist, verankern Sie den regulären Ausdruck mit einem '^' oder '$' Zeichen oder erstellen Sie einen spezifischeren regulären Ausdruck.

Die Manpage nur erwähnt ., ?und *, aber es ist unvollständig , wie +, |, [, ^, und $ist auch ausreichend zu lassen apt-getoder aptdas Muster als regulärer Ausdruck interpretiert. 3

Obwohl Sie eine beliebige Anzahl von Zeichen mit .*- nicht nur - *übereinstimmen können, benötigen Sie dies nur, wenn es in der Mitte Ihres regulären Ausdrucks erscheinen würde. Da das Muster mit einer beliebigen Teilzeichenfolge eines Paketnamens abgeglichen wird, ist es am Ende (oder am Anfang) des Musters sinnlos.

Die Manpage erwähnt ^und$ . Diese (vor allem ^) sind die Schlüssel zum Schreiben von sicheren, effizienten Mustern für die Verwendung mit den install, removeoder purgeAktionen in aptoder apt-get.

  • ^Verankert einen regulären Ausdruck am Anfang der gesamten Zeichenfolge. ^k3bwählt alle Pakete , deren Namen beginnen mit k3b.
  • $Verankert einen regulären Ausdruck am Ende der gesamten Zeichenfolge. k3b$würde wählen Sie alle Pakete , deren Namen enden mit k3b.

Daher können Sie diesen Befehl verwenden, um die Pakete sicher zu entfernen:

sudo apt-get remove ^k3b

Schließlich können Sie in dem von Ihnen erwähnten speziellen Fall auch beide Namen selbst übergeben:

sudo apt-get remove k3b k3b-data

Dann vermeiden Sie diese Komplexität! (Obwohl das Verankern mit ^einfach ist, wenn Sie es gewohnt sind.) Oder verwenden Sie die Klammererweiterung , die Ihre Shell zu dem obigen Befehl erweitert:

sudo apt-get remove k3b{,-data}

1 Es gibt zwei Ausnahmen: (a) einige Optionen (zB -f, --purge) werden erkannt, und (b) einige Satzzeichen auf dem erscheinende Ende eines Arguments , das sonst als Paketnamen genommen würde , um die Aktion auszuführen , kann sein wird verwendet, um zu ändern, was getan wird (z. B. sudo apt install ubuntu-desktop^installiert die Task anstelle des Pakets und wann ^am Ende angezeigt wird).

2 Andere Metazeichen für reguläre Ausdrücke sind vorhanden. Zum Beispiel \wird von allen Dialekten regulärer Ausdrücke unterstützt und häufig verwendet. ., ?, +, *, |, [, ^, Und $nur zufällig die Metazeichen werden der APT - Entwickler als regulärer Ausdruck auslösen würde Interpretation entschieden (nach Auflösung als exaktes Paket mit dem Namen ausgefallen ist ).

3 Der einfachste Weg, dies zu überprüfen, besteht darin, die Installation oder Deinstallation mit einem solchen Muster zu simulieren. Verwenden Sie dazu die -soben beschriebene Option. Wenn Sie beispielsweise apt -s install ^virtualboxShows sudo apt install ^virtualboxausführen, wird versucht, jedes Paket zu installieren, über das der Paketmanager weiß, mit wem der Name beginnt virtualbox. Dieses Verhalten kann jedoch auch durch Untersuchen des Quellcodes überprüft werden . Überprüfen Sie die CacheSetHelper::PackageFromRegExFunktion in cacheset.cc.

Eliah Kagan
quelle
1

Sie entfernen dann wahrscheinlich eine Bibliothek, in der k3b enthalten ist, von der diese Programme abhängen.

Kurz gesagt, Sie werden es vielleicht nie erfahren. Ich empfehle, kein Platzhalterzeichen zu verwenden, um Dinge zu entfernen und zu lesen, wenn Sie dazu aufgefordert werden (Entschuldigung).

Auch ohne die -n Regex-Suche werden alle Felder und nicht nur Namen verwendet

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

Auch qbi ist korrekt. Ihre Regex ist von Anfang an fehlerhaft

coteyr
quelle
Eine andere Sache, in Fällen wie Ihren (k3b und k3b Daten) nur apt-K3b deinstallieren. Apt informiert Sie dann, wenn Sie Dinge installiert haben, die Sie nicht mehr benötigen, und was Sie tun müssen, um sie zu entfernen.
Coteyr
Wow! Ich hätte nie erwartet, dass es auch in Beschreibungen sucht! Ja, das werde ich definitiv nie wieder tun! (und ich werde sicher das nächste Mal lesen: P)
Steve Goykovich
Die Verknüpfung ist unterbrochen. Würde es Ihnen etwas ausmachen, die Verwendung des -n zu klären?
Seanny123
-n bedeutet, dass nur im Namensfeld gesucht wird.
Coteyr
Nach dem Versuch wird die Option -n nicht apt-get removenur von erkannt apt-get cache. Es scheint, dass tatsächlich apt-get removenur nach Paketnamen gesucht wird, nicht nach Beschreibungen.
Boris Dalstein