apt-get remove con carattere jolly rimosso molto più del previsto. perché?


38

Ieri sera stavo cercando di masterizzare CD. Essendo seccato con k3b e scegliendo invece di usare brasero, sono andato a rimuovere k3b.

Ho inserito:

sudo apt-get remove k3b

Ho colpito due volte tab e ho visto che avevo entrambi i dati k3b e k3b sul mio sistema. Supponendo che non avrei bisogno di dati k3b sul mio sistema senza k3b, volevo anche rimuoverlo, quindi ho digitato:

sudo apt-get remove k3b*

Purtroppo ho premuto Y per confermare senza guardare. Ha disinstallato molto più di k3be k3b-data. Ha disinstallato i pacchetti che non si adattavano al mio k3b*regex. Ad esempio: transmissione network-manager.

Sono abbastanza certo di non avere uno spazio tra k3be *ma non so perché altrimenti rimuoverà tutto ciò che ha fatto. C'è qualcosa in apt-get che sto fraintendendo?


Risposte:


38

Il comando che vuoi è sudo apt-get remove '^k3b.*', perché:

  • Devi .*abbinare qualsiasi personaggio, un numero qualsiasi di volte
  • Devi ^abbinare l'inizio della stringa
  • Devi citare la regex per impedire a bash di interpretare *come jolly

(Questa risposta completa e sintetizza le informazioni precedenti fornite da qbi e Flimm)


5
Questo è sicuro ed è ok per usarlo ma non è necessario .*. Puoi semplicemente usare sudo apt-get remove ^k3b. La presenza di ^è sufficiente per far sì che l'argomento venga interpretato come un'espressione regolare e quando apto apt-getinterpreta un argomento come espressione regolare, lo trova ovunque nel nome del pacchetto. Ecco perché è necessario ^--to ancora la partita per l'inizio del nome del pacchetto. L'espressione regolare non ha bisogno di corrispondere all'intero nome del pacchetto, solo una parte di esso.
Eliah Kagan,

1
@EliahKagan Thx per le informazioni aggiuntive! (e in effetti, ha senso che se ne hai bisogno ^, allora non ne hai bisogno .*)
Boris Dalstein,

30

L'espressione regolare *rappresenta zero o arbitrariamente molti. Quindi hai detto apt-getdi rimuovere tutto ciò che contiene k3seguito da un numero qualsiasi di b, quindi praticamente tutto ciò che contiene k3. Se provo il tuo comando sul mio sistema, voglio rimuovere 58 pacchetti.

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.

ugh! Sono stato bloccato a lavorare su queste maledette macchine Windows (dove * significa semplicemente "e qualsiasi cosa dopo") per troppo tempo!
Steve Goykovich,

14
Il *funziona come abbreviazione per bash come in DOS, ma alcuni comandi come apt-getaspettarsi una regex. Durante la digitazione sudo apt-get remove -s k3b*, bash cercherà innanzitutto tutti i file nella directory corrente che iniziano con k3b. Se ne trova, sostituirà tale argomento con quei nomi di file. In caso contrario, passerà k3b*direttamente a apt-get, che lo interpreterà come una regex. Se non vuoi che bash interpreti prima l'asterisco come un carattere jolly (cosa che probabilmente non ti piace), circondi l'argomento con virgolette singole, in questo modo:sudo apt-get remove -s 'k3b*'
Flimm

3
Quindi il comando previsto sarebbe stato sudo apt-get remove -s 'k3b.*'. Mi sono appena imbattuto in questa risposta e l'ho trovato davvero importante da sapere. IMHO questo è abbastanza inaspettato e lo contrassegnerei come un bug "comportamento imprevisto" di apt-get ... normalmente ti aspetti un significato "glob" e non "regexp" se non specificato. Grazie comunque e +1!
Rmano,

1
E per quelli come me che non lo sapevano: l' -sopzione significa "simulazione". Indica di apt-getnon eseguire l'operazione, ma semplicemente di informarti di ciò che accadrebbe senza l' -sopzione.
Boris Dalstein,

Penso che il tuo uso di virgolette singole per creare globbing NON funzioni, almeno nel pupazzo. E questo è inaspettato. Nel programma 'find', se scrivo find / -iname 'project *' troverò tutto ciò che inizia con il progetto, non qualcosa che ha 'project' in esso e qualcosa dopo. Come prova per quanto riguarda le marionette, noti come i miei risultati dicono "regex", e i risultati lo dimostrano?
Dennis,

9

Usa sudo apt-get remove ^k3binvece. Quando installi o rimuovi pacchetti, *è spesso pericoloso e raramente necessario. Se lo usi *, dovresti citarlo, ma ciò non lo rende più sicuro, perché la sua tendenza a selezionare molti più pacchetti di quelli che intendi è il risultato del modo apte l' apt-getinterpretazione e non un effetto dell'espansione del nome percorso .

  • Anche gli usi sicuri di questi* sono spesso inutili .
  • Gli usi non sicuri sono brutali . La rimozione k3b*rimuove ogni pacchetto che contiene k3 ovunque nel suo nome (e ogni pacchetto che dipende da tale pacchetto). Questo non è un refuso - contenente k3è sufficiente, anche senza il b, perché b*significa "zero o più bs".

Quando si esegue apto apt-getcon la install, removeo purgeazione, ogni argomento successivo viene dapprima 1 interpretato come il nome di un singolo pacchetto. Se esiste un pacchetto con quel nome esatto, l'azione viene eseguita per esso.

Se non v'è tale pacchetto, apte apt-getsi controlla se l'argomento contiene una qualsiasi delle comuni espressioni regolari metacaratteri 2 . , ?, +,* , |, \[, ^, o$ . In caso contrario, è fatto: non è stato trovato alcun pacchetto.

Se non contiene alcuna di quei personaggi, allora è considerato come un'espressione regolare e confrontata con qualsiasi parte di qualsiasi nome del pacchetto. Non deve corrispondere al nome intero. Come altri hanno già detto, *in un'espressione regolare non significa la stessa cosa *di un glob. ?neanche. In un'espressione regolare:

  • *consente all'elemento precedente di apparire un numero qualsiasi di volte, incluso solo una volta o per niente, anziché esattamente una volta.
  • ?rende facoltativo l' elemento precedente , ovvero consente di apparire zero o una volta.

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

Se nessun pacchetto corrisponde all'espressione data e l'espressione contiene uno di '.', '?' o '*' quindi si presume che sia un'espressione regolare POSIX e viene applicato a tutti i nomi di pacchetto nel database. Eventuali corrispondenze vengono quindi installate (o rimosse). Si noti che la corrispondenza viene eseguita dalla sottostringa in modo che "lo. *" Corrisponda a "how-lo" e "minimo". Se ciò non è desiderato, ancorare l'espressione regolare con un carattere '^' o '$' o creare un'espressione regolare più specifica.

La manpage menziona solo ., ?e *, ma è incompleta , come +, |, [, ^, e $sono anche sufficienti per consentire apt-geto aptinterpretare il modello come un'espressione regolare. 3

Anche se puoi abbinare un numero qualsiasi di caratteri con .*- non solo - hai* bisogno di questo solo se apparirebbe nel mezzo della tua espressione regolare. Poiché il modello è abbinato a qualsiasi sottostringa del nome di un pacchetto, è inutile alla fine (o all'inizio) del modello.

La manpage menziona ^e$ . Questi (in particolare ^) sono la chiave per la scrittura di sicurezza, i modelli efficienti per l'utilizzo con i install, removeo purgeazioni apto apt-get.

  • ^fissa un'espressione regolare all'inizio dell'intera stringa. ^k3bseleziona tutti i pacchetti i cui nomi iniziano con k3b.
  • $ancora un'espressione regolare alla fine dell'intera stringa. k3b$selezionerebbe tutti i pacchetti i cui nomi finiscono con k3b.

Pertanto è possibile utilizzare questo comando per rimuovere in sicurezza i pacchetti:

sudo apt-get remove ^k3b

Infine, nel caso specifico che hai citato, potresti anche passare tu stesso entrambi i nomi:

sudo apt-get remove k3b k3b-data

Quindi eviti tutta questa complessità! (Anche se l'ancoraggio con ^è semplice una volta che ci sei abituato.) O usa l' espansione del controvento , che la tua shell espande nel comando sopra:

sudo apt-get remove k3b{,-data}

1 Ci sono due eccezioni a questo: (a) alcune opzioni (ad es. -f, --purge) Sono riconosciute, e (b) alcuni caratteri di punteggiatura che appaiono alla fine di un argomento che altrimenti verrebbero presi come nome del pacchetto per eseguire l'azione usato per modificare ciò che viene fatto (ad esempio, sudo apt install ubuntu-desktop^installa l' attività anziché il pacchetto e quando ^appare alla fine).

2 Esistono altri metacaratteri di espressioni regolari. Ad esempio, \è supportato da tutti i dialetti delle espressioni regolari e comunemente usato. ., ?, +, *, |, [, ^, E $capita di essere i metacaratteri gli sviluppatori hanno deciso di APT farebbe scattare l'interpretazione come un'espressione regolare (dopo la risoluzione come un pacchetto di nome esatto non è riuscita).

3 Il modo più semplice per verificarlo è simulare l'installazione o la rimozione con tale modello, utilizzando l' -sopzione come descritto sopra. Ad esempio, l'esecuzione apt -s install ^virtualboxmostra che sudo apt install ^virtualboxavrebbe l'effetto di tentare di installare tutti i pacchetti che il gestore pacchetti conosce sul nome con cui inizia virtualbox. Tuttavia, questo comportamento può essere verificato anche esaminando il codice sorgente . Controlla la CacheSetHelper::PackageFromRegExfunzione in cacheset.cc.


1

Molto probabilmente rimuoverai una lib che conteneva k3b da cui dipendevano quei programmi.

Insomma potresti non saperlo mai. Consiglio di non usare un carattere jolly per rimuovere oggetti e leggere cose quando richiesto (scusate).

Inoltre senza le ricerche regex -n usa tutti i campi e non solo i nomi

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

anche qbi è corretto il tuo regex è difettoso sin dall'inizio


Un'altra cosa, in casi come i tuoi (dati k3b e k3b) basta apt-get disinstallare k3b. Apt ti informerà se hai cose installate che non ti servono più e cosa devi fare per rimuoverle.
coteyr,

Wow! Non mi sarei mai aspettato che cercasse anche nelle descrizioni! sì, questo è sicuramente qualcosa che non farò mai più! (e sarò sicuro di leggere le cose la prossima volta: P)
Steve Goykovich il

Il collegamento è interrotto, ti dispiacerebbe chiarire come usare il -n?
Seanny123,

-n significa solo cercare nel campo dei nomi.
Coteyr,

Dopo aver provato, l'opzione -n ​​non viene riconosciuta da apt-get remove, solo da apt-get cache. Sembra che in realtà apt-get removecerchi solo nomi di pacchetti, non descrizioni.
Boris Dalstein,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.