apt-get remove con comodín eliminado mucho más de lo esperado. ¿por qué?

38

Anoche estaba intentando grabar CD. Estando molesto con k3b y optando por usar brasero en su lugar, fui a eliminar k3b.

Escribí en:

sudo apt-get remove k3b

Presioné la tecla dos veces y vi que tenía datos k3b y k3b en mi sistema. Suponiendo que no necesitaría k3b-data en mi sistema sin k3b, también quería eliminarlo, así que escribí:

sudo apt-get remove k3b*

Lamentablemente presioné Y para confirmar sin mirar. Desinstaló mucho más que k3by k3b-data. Desinstaló paquetes que no se ajustaban a mi k3b*expresión regular. Por ejemplo: transmissiony network-manager.

Estoy bastante seguro de que no tuve un espacio entre k3by, *pero no sé por qué más eliminaría todo lo que hizo. ¿Hay algo sobre apt-get que no entiendo?

Steve Goykovich
fuente

Respuestas:

38

El comando que quieres es sudo apt-get remove '^k3b.*'porque:

  • Necesitas .*hacer coincidir cualquier personaje, cualquier cantidad de veces
  • Debes ^hacer coincidir el inicio de la cadena
  • Debe citar la expresión regular para evitar que bash se interprete *como un comodín

(Esta respuesta completa y resume la información previa proporcionada por qbi y Flimm)

Boris Dalstein
fuente
55
Esto es seguro y está bien usarlo, pero no necesita el .*. Solo puedes usar sudo apt-get remove ^k3b. La presencia de ^es suficiente para hacer que el argumento se interprete como una expresión regular, y cuando apto apt-getinterpreta un argumento como una expresión regular, coincide en cualquier parte del nombre del paquete. Es por eso que necesita ^--a ancla el partido al comienzo del nombre del paquete. La expresión regular no necesita coincidir con el nombre completo del paquete, solo con cualquier parte del mismo.
Eliah Kagan
1
@EliahKagan Thx para la información adicional! (y de hecho, tiene sentido que si lo necesitas ^, entonces no lo necesites .*)
Boris Dalstein
30

La expresión regular *significa cero o arbitrariamente muchos. Entonces le dijiste apt-getque eliminara todo lo que contiene k3seguido de cualquier cantidad de b, básicamente todo lo que contiene k3. Si pruebo su comando en mi sistema, quiere eliminar 58 paquetes.

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
fuente
ugh! ¡He estado atrapado trabajando en estas malditas máquinas Windows (donde * solo significa "y cualquier cosa después") durante demasiado tiempo!
Steve Goykovich
14
El *hace el trabajo como un comodín para fiesta al igual que en DOS, pero algunos comandos como apt-getesperar que una expresión regular. Cuando escribe sudo apt-get remove -s k3b*, bash primero buscará cualquier archivo en su directorio actual que comience con k3b. Si encuentra alguno, reemplazará ese argumento con esos nombres de archivo. Si no, pasará k3b*directamente a apt-get, lo que lo interpretará como una expresión regular. Si no desea que bash interprete el asterisco como comodín primero (lo que probablemente no quiera), rodee el argumento con comillas simples, como esta:sudo apt-get remove -s 'k3b*'
Flimm
3
Entonces el comando previsto habría sido sudo apt-get remove -s 'k3b.*'. Me topé con esta respuesta y me pareció muy importante saberlo. En mi humilde opinión, esto es bastante inesperado y lo marcaría como un error de "comportamiento inesperado" de apt-get ... normalmente espera un significado "glob" y no un significado "regexp" si no se especifica. Gracias de todos modos y +1!
Rmano
1
Y para aquellos como yo que no lo sabían: la -sopción significa "simulación". Le indica que apt-getno realice la operación, sino simplemente que le informe de lo que sucedería sin la -sopción.
Boris Dalstein
Creo que el uso de comillas simples para crear globbing NO funciona, al menos en títeres. Y eso es inesperado. En el programa 'find', si escribo find / -iname 'project *' encontraré todo lo que comience con project, no algo que tenga 'project' en él y nada más. Como prueba con respecto a la marioneta, observe cómo mis resultados dicen 'regex' y los resultados lo prueban.
Dennis
9

Usar en su sudo apt-get remove ^k3blugar. Cuando instala o elimina paquetes, a *menudo es peligroso y rara vez se necesita. Si lo usa *, debe citarlo, pero eso no lo hace más seguro, porque su tendencia a seleccionar muchos más paquetes de los que desea es el resultado de la forma apte apt-getinterpretación y no un efecto de la expansión del nombre de ruta .

  • Incluso los usos seguros de a *menudo son innecesarios .
  • Los usos inseguros son brutales . Al eliminar, se k3b*eliminan todos los paquetes que contienen k3 cualquier parte de su nombre (y cada paquete que depende de dicho paquete). Eso no es un error tipográfico, k3es suficiente, incluso sin el b, porque b*significa "cero o más bs".

Cuando se ejecuta apto apt-getcon el install, removeo purgeacción, cada argumento subsiguiente es primero 1 interpretado como el nombre de un paquete individual. Si existe un paquete con ese nombre exacto, la acción se realiza para él.

Si no hay tal paquete, apty apt-getcomprobará si el argumento contiene cualquiera de los comunes de expresiones regulares metacaracteres 2 . , ?, +,* , |, \[, ^, o$ . Si no, está hecho, no se encontró ningún paquete.

Si no contiene ninguno de esos personajes, a continuación, se trata como una expresión regular y compara con cualquier parte de cualquier nombre de paquete. No tiene que coincidir con el nombre completo. Como han dicho otros, *en una expresión regular no significa lo mismo que *en un globo. ?tampoco. En una expresión regular:

  • *permite que el elemento anterior aparezca cualquier cantidad de veces, incluso una sola vez o ninguna, en lugar de exactamente una vez.
  • ?hace que el elemento anterior sea opcional , es decir, le permite aparecer cero o una vez.

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

Si ningún paquete coincide con la expresión dada y la expresión contiene uno de '.', '?' o '*', entonces se supone que es una expresión regular POSIX, y se aplica a todos los nombres de paquetes en la base de datos. Las coincidencias se instalan (o eliminan). Tenga en cuenta que la coincidencia se realiza mediante una subcadena, por lo que 'lo. *' Coincide con 'how-lo' y 'lower'. Si esto no es deseado, ancle la expresión regular con un carácter '^' o '$', o cree una expresión regular más específica.

La página de manual sólo menciona ., ?y *, pero es incompleta , ya que +, |, [, ^, y $también son suficientes para permitir apt-geto aptinterpretar el patrón como una expresión regular. 3

Aunque puede hacer coincidir cualquier número de caracteres con .*, no solo, *solo necesita esto si aparece en el medio de su expresión regular. Debido a que el patrón se compara con cualquier subcadena del nombre de un paquete, no tiene sentido al final (o principio) del patrón.

La página de manual menciona ^y$ . Estos (especialmente ^) son clave para escribir patrones seguros y eficaces para su uso con los install, removeo purgeacciones en apto apt-get.

  • ^ancla una expresión regular al comienzo de toda la cadena. ^k3bselecciona todos los paquetes cuyos nombres comienzan con k3b.
  • $ancla una expresión regular al final de toda la cadena. k3b$seleccionaría todos los paquetes cuyos nombres terminen en k3b.

Por lo tanto, puede usar este comando para eliminar de forma segura los paquetes:

sudo apt-get remove ^k3b

Finalmente, en el caso específico que mencionó, podría pasar ambos nombres usted mismo:

sudo apt-get remove k3b k3b-data

¡Entonces evitas toda esta complejidad! (Aunque anclar con ^es simple una vez que está acostumbrado). O use la expansión de llaves , que su caparazón se expande en el comando anterior:

sudo apt-get remove k3b{,-data}

1 Hay dos excepciones a esto: (a) se reconocen algunas opciones (p. Ej. -f, --purge) Y (b) algunos caracteres de puntuación que aparecen al final de un argumento que de otro modo se tomarían como un nombre de paquete para realizar la acción. se usa para alterar lo que se hace (por ejemplo, sudo apt install ubuntu-desktop^instala la tarea en lugar del paquete, y cuando ^aparece al final).

2 Existen otros metacaracteres de expresiones regulares. Por ejemplo, \es compatible con todos los dialectos de expresiones regulares y de uso común. ., ?, +, *, |, [, ^, Y $acaba de pasar a ser los metacaracteres los desarrolladores decidieron APT daría lugar a la interpretación como una expresión regular (después de la resolución como un paquete llamado exacta ha fallado).

3 La forma más fácil de verificar esto es simular la instalación o eliminación con dicho patrón, utilizando la -sopción como se describe anteriormente. Por ejemplo, ejecutar apt -s install ^virtualboxprogramas que sudo apt install ^virtualboxtendrían el efecto de intentar instalar todos los paquetes que el administrador de paquetes conoce sobre el nombre de quién comienza virtualbox. Sin embargo, este comportamiento también se puede verificar examinando el código fuente . Verifique la CacheSetHelper::PackageFromRegExfunción en cacheset.cc.

Eliah Kagan
fuente
1

Es más probable que elimine una lib que tenía k3b de la que dependían esos programas.

En resumen, es posible que nunca sepas. Recomiendo no usar un comodín para eliminar cosas y leer cosas cuando se le solicite (lo siento).

Además, sin las búsquedas de expresiones regulares -n, se usan todos los campos y no solo los nombres

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

También qbi es correcto, su expresión regular es defectuosa desde el primer momento

coteyr
fuente
Otra cosa, en casos como el tuyo (datos k3b y k3b) simplemente apt-get desinstalar k3b. Apt le informará si tiene instaladas cosas que ya no necesita, y qué debe hacer para eliminarlas.
Coteyr
¡Guauu! ¡Nunca hubiera esperado que buscara dentro de las descripciones también! ¡Sí, esto es definitivamente algo que nunca volveré a hacer! (y me aseguraré de leer las cosas la próxima vez: P)
Steve Goykovich el
El enlace está roto, ¿te importaría aclarar cómo usar -n?
Seanny123
-n significa solo buscar en el campo de nombres.
coteyr
Después de intentarlo, la opción -n no es reconocida por apt-get remove, solo por apt-get cache. Parece que en realidad apt-get removesolo busca nombres de paquetes, no descripciones.
Boris Dalstein