Existe uma ferramenta de análise de nome que faz parte do pacote oficial de ferramentas RPM?
Eu tenho uma lista de nomes de arquivos. Cada um é o nome do arquivo de um pacote RPM. Eu não tenho os pacotes reais, apenas os nomes dos arquivos. Para cada um, preciso extrair o nome e a versão do pacote ($ NAME e $ VERSION). A razão pela qual eu preciso disso é que estou escrevendo um script que garante que "yum install $ VERSION" instale $ VERSION. Isso faz parte de um sistema que cria pacotes e verifica se eles foram enviados corretamente.
A lista de nomes de arquivos é semelhante a:
$ 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
Encontrei o seguinte código, que é uma função BASH que executa a tarefa:
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. Na maioria das vezes. Existem algumas exceções:
$ parse_rpm CentOS/6/x86_64/sei_dnsmaster-1.0-99.el6.x86_64.rpm
sei_dnsmaster 1.0 99.el6 x86_64
Observe que ela não obteve a versão corretamente (deve ser 1.0-99)
Gostaria de saber (1) se existe uma ferramenta no pacote rpmdev que faz isso corretamente. (2) Caso contrário, existe um regex oficial que eu poderia usar. (3) Qual é o equivalente python desse regex?
Desde já, obrigado!
Respostas:
Você não precisa fazer nada disso; O RPM possui um argumento de formato de consulta que permite especificar exatamente os dados que você deseja receber. Ele até produzirá sem terminações de linha se você não as especificar.
Por exemplo:
A lista completa de variáveis que você pode usar pode ser obtida com:
Observe que, no caso de
RELEASE
, saída como84.el6
é normal e esperada, pois é assim que os pacotes RPM são versionados quando empacotados por ou para uma distribuição.fonte
$ 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
Foi-me dito que a maneira oficial de fazer o que estou procurando é no Python:
Eu escrevi um pequeno programa Python que faz o que eu preciso. Vou oferecer o script para o projeto rpmdev para inclusão.
fonte
Elaborei expressões regulares que se encaixavam em todos os dados com os quais eu era capaz de testá-las. Eu tive que usar uma mistura de combinações gananciosas e não gananciosas. Dito isto, aqui estão minhas versões perl e python:
Perl:
Pitão:
Prefiro ter uma regex que vem do projeto RPM. O que eu inventei acima terá que fazer por enquanto.
fonte
.*
menos que você realmente queira corresponder a algo). É bom ver que você encontrou sozinho!AdbeRdr9.5.5-1_i486linux_enu.rpm
) que interrompe a análise de expressões regulares acima.Os arquivos RPM podem ter nomes de arquivos descolados em casos extremos, mas geralmente você pode dividir o NVR nos hífens. O problema é que a parte N (nome) do NVR pode conter hífens e sublinhados, mas é garantido que o V (versão) e o R (release) não possuem hífens estranhos. Assim, você pode começar aparando a parte VR para obter um Nome.
Com base nisso, você pode isolar a parte Versão e Liberação.
Basta dividir o hífen novamente para isolar a parte que você precisa. E, obviamente, limpe as strings de extensão de arquivo arch e rpm, o que é um dado. Apenas fornecendo uma idéia de como isso pode ser abordado no bash.
fonte
Use as opções -q --queryformat do rpm, como dito anteriormente, se você quiser fazer isso em um pacote não instalado, poderá especificar o rpm com a
-p
opção, assim:por exemplo
me dá
apenas dividir o nome do arquivo está errado!
então preste atenção , este não é o detalhe correto da rotação, por exemplo,
1.fedora
está realmente1.fc10
na rotação.fonte
Se você estiver familiarizado com expressões regulares e / ou Perl, isso é bastante fácil.
ou apenas a regex:
Se você dividir, é isso:
[^\-]+
(escapou porque o hífen tem um significado especial nos grupos de caracteres)[^\-]+?
([^\-]+?)
([^\-]+?)-
.rpm
):([^\-]+?)-(.*).rpm$
(o dólar significa "fim de linha")m#([^\-]+?)-(.*).rpm$#
Feito ! Apenas pegue as duas partes nas variáveis
$1
e$2
Comente o primeiro one-liner:
Eu estava em um diretório com muitos arquivos rpm, daí o
ls
.perl -p
é equivalente a ;O que explica que eu tive que inserir uma sequência nula
$_
para evitar a impressão perl na linha depois de extraí-la e imprimi-la personalizada. Note que eu poderia ter usado substituições para evitar esse pequeno 'hack'.fonte
module-init-tools-3.9-21.el6_4.x86_64.rpm
.IMHO a maneira mais simples de shell é:
Ou seja: reverter cada linha, usando a barra de corte apenas a primeira parte ( emanelif ), em seguida, usando hífen cortar tudo, mas as duas primeiras partes (isto é, deixar para trás ESAELER incluindo emanelif eth fo TSER e NOISREV ) e inverter o ENIL volta.
Com o seu arquivo de exemplo:
Obter outras peças é um exercício de leitura de corte (1) .
fonte
Você pode utilizar
dnf info
. Aqui está um exemplo de script Bash para obter valores e definir como uma variável:Isso dará um resultado mesmo se o pacote não estiver instalado.
fonte