¿Existe una herramienta de análisis de nombres que sea parte del paquete oficial de herramientas RPM?
Tengo una lista de nombres de archivo. Cada uno es el nombre de archivo de un paquete RPM. No tengo los paquetes reales, solo los nombres de archivo. Para cada uno, necesito extraer el nombre y la versión del paquete ($ NAME y $ VERSION). La razón por la que necesito esto es porque estoy escribiendo un script que luego se asegura de que "yum install $ VERSION" instale $ VERSION. Esto es parte de un sistema que crea paquetes y verifica que estén cargados correctamente.
La lista de nombres de archivo se ve así:
$ cat /tmp/packages.txt
/home/builder/packages/testing-dev/CentOS/6/x86_64/emacs-mercurial-2.8-3.el6.x86_64.rpm
/home/builder/packages/testing-dev/CentOS/6/x86_64/emacs-mercurial-el-2.8-3.el6.x86_64.rpm
/home/builder/packages/testing-dev/CentOS/6/x86_64/mercurial-2.8-3.el6.x86_64.rpm
/home/builder/packages/testing-dev/CentOS/6/x86_64/mercurial-hgk-2.8-3.el6.x86_64.rpm
/home/builder/packages/testing-dev/CentOS/6/x86_64/python-redis-2.8.0-2.el6.noarch.rpm
/home/builder/packages/testing-dev/CentOS/6/x86_64/redis-2.6.16-1.el6.1.x86_64.rpm
/home/builder/packages/testing-dev/CentOS/6/x86_64/sei_dnsmaster-1.0-99.el6.x86_64.rpm
Encontré el siguiente código, que es una función BASH que hace la tarea:
function parse_rpm() { RPM=$1;B=${RPM##*/};B=${B%.rpm};A=${B##*.};B=${B%.*};R=${B##*-};B=${B%-*};V=${B##*-};B=${B%-*};N=$B;echo "$N $V $R $A"; }
for i in $(</tmp/packages.txt) ; do
parse_rpm $i
done
Funciona. Principalmente. Hay algunas excepciones:
$ parse_rpm CentOS/6/x86_64/sei_dnsmaster-1.0-99.el6.x86_64.rpm
sei_dnsmaster 1.0 99.el6 x86_64
Tenga en cuenta que no obtuvo la versión correctamente (debería ser 1.0-99)
Me pregunto (1) si hay una herramienta en el paquete rpmdev que hace esto correctamente. (2) Si no, ¿hay una expresión regular oficial que pueda usar? (3) ¿Cuál es el equivalente en python de esa expresión regular?
¡Gracias por adelantado!
Respuestas:
No necesitas hacer nada de esto; RPM tiene un argumento de formato de consulta que le permitirá especificar exactamente los datos que desea recibir. Incluso saldrá sin terminaciones de línea si no las especifica.
Por ejemplo:
La lista completa de variables que puede usar se puede obtener con:
Tenga en cuenta que, en el caso de
RELEASE
, la salida como84.el6
es normal y esperada, ya que así es como se versionan los paquetes RPM cuando se empaquetan por o para una distribución.fuente
$ rpm --queryformat "%{NAME} %{VERSION} %{RELEASE} %{ARCH}" -q CentOS/6/x86_64/sei_dnsmaster-1.0-84.el6.x86_64.rpm package CentOS/6/x86_64/sei_dnsmaster-1.0-84.el6.x86_64.rpm is not installed
libopenssl0_9_8-32bit-0.9.8j-0.26.1_0.50.1.x86_64.delta.rpm
Me dijeron que la forma oficial de hacer lo que estoy buscando es en Python:
He escrito un breve programa de Python que hace lo que necesito. Ofreceré el script al proyecto rpmdev para su inclusión.
fuente
Trabajé expresiones regulares que se ajustan a todos los datos con los que pude probarlas. Tuve que usar una mezcla de partidos codiciosos y no codiciosos. Dicho esto, aquí están mis versiones de Perl y Python:
Perl:
Pitón:
Prefiero tener una expresión regular que proviene del proyecto RPM. El que inventé arriba tendrá que hacer por ahora.
fuente
.*
menos que REALMENTE quiera hacer coincidir algo). ¡Sin embargo, es bueno ver que lo encontraste solo!AdbeRdr9.5.5-1_i486linux_enu.rpm
) que rompe su análisis de expresiones regulares arriba.Los archivos Rpm pueden tener algunos nombres de archivos originales en casos extremos, pero generalmente puede dividir el NVR en los guiones. El problema es que la porción N (nombre) del NVR puede contener guiones y guiones bajos, pero se garantiza que la V (versión) y R (versión) no tienen guiones extraños. Por lo tanto, puede comenzar recortando la porción VR para derivar un Nombre.
Partiendo de eso, puede aislar la porción Versión y Release.
Simplemente divida el guión nuevamente para aislar la parte que necesita. Y obviamente, limpie las cadenas de extensión de archivo de arco y rpm, lo cual es un hecho. Solo te doy una idea de cómo podría abordarse en bash.
fuente
Use las opciones -q --queryformat de rpm como se dijo anteriormente, si desea hacer esto en un paquete no instalado, puede especificar las rpm con la
-p
opción, de esta manera:p.ej
me da
¡así que dividir el nombre de archivo está mal!
así que preste atención , estos no son los detalles correctos de las rpm, por ejemplo,
1.fedora
está realmente1.fc10
en las rpm.fuente
Si está familiarizado con las expresiones regulares y / o Perl, eso es bastante fácil.
o solo la expresión regular:
Si lo divide eso es:
[^\-]+
(escapó porque el guión tiene un significado especial en los grupos de caracteres)[^\-]+?
([^\-]+?)
([^\-]+?)-
.rpm
):([^\-]+?)-(.*).rpm$
(el dólar significa "fin de línea")m#([^\-]+?)-(.*).rpm$#
Hecho ! Simplemente obtenga ambas partes en las variables
$1
y$2
Comenta sobre el primer one-liner:
Estaba en un directorio con muchos archivos rpm, de ahí el
ls
.perl -p
es equivalente a ;Lo que explica que tuve que poner una cadena nula
$_
para evitar que Perl volviera a imprimir la línea después de extraerla y personalizarla. Tenga en cuenta que podría haber usado sustituciones para evitar este pequeño 'truco'.fuente
module-init-tools-3.9-21.el6_4.x86_64.rpm
.En mi humilde opinión, la forma de shell más simple es:
Es decir: invierta cada línea, usando una barra cortada solo en la primera parte ( emanelif ), luego use un guión cortado en todas las primeras dos partes (es decir, deje ESAELER incluido emanelif eth foser y NOISREV ) e invierta el enil back.
Con su archivo de ejemplo:
Para obtener otras partes es ejercicio en lectura corte (1) .
fuente
Puedes utilizar
dnf info
. Aquí hay un ejemplo de script Bash para obtener valores y establecer como una variable:Dará un resultado incluso si el paquete no está instalado.
fuente