RPM 이름을 구성 요소로 구문 분석


19

공식 RPM 도구 패키지의 일부인 이름 구문 분석 도구가 있습니까?

파일 이름 목록이 있습니다. 각각은 RPM 패키지의 파일 이름입니다. 실제 패키지가 없으며 파일 이름 만 있습니다. 각각에 대해 패키지 이름과 버전 ($ NAME 및 $ VERSION)을 추출해야합니다. 내가 필요한 이유는 "yum install $ VERSION"이 $ VERSION을 설치하는지 확인하는 스크립트를 작성하고 있기 때문입니다. 패키지를 빌드하고 올바르게 업로드되었는지 확인하는 시스템의 일부입니다.

파일 이름 목록은 다음과 같습니다.

$ 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

작업을 수행하는 BASH 함수 인 다음 코드 를 찾았 습니다 .

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

효과가있다. 대개. 몇 가지 예외가 있습니다 :

$ parse_rpm CentOS/6/x86_64/sei_dnsmaster-1.0-99.el6.x86_64.rpm
sei_dnsmaster 1.0 99.el6 x86_64

버전을 올바르게 얻지 못했습니다 (1.0-99 여야 함)

rpmdev 패키지 에이 작업을 올바르게 수행하는 도구가 있는지 궁금합니다. (2) 그렇지 않으면 공식 정규식이 있습니까? (3) 그 정규 표현식과 파이썬은 무엇입니까?

미리 감사드립니다!


입력을받는 위치와 입력 형식을 명확히 할 수 있습니까?
user9517은 GoFundMonica 지원

답변:


25

이 작업을 수행 할 필요는 없습니다. RPM에는 쿼리 형식 인수가있어 수신하려는 데이터를 정확하게 지정할 수 있습니다. 지정하지 않으면 줄 끝없이 출력됩니다.

예를 들어 :

rpm --queryformat "%{NAME} %{VERSION} %{RELEASE} %{ARCH}" -q coreutils
rpm --queryformat "The version of %{NAME} is %{VERSION}\n" -q coreutils

rpm --queryformat "%{NAME} %{VERSION} %{RELEASE} %{ARCH}" -qp file.rpm

사용할 수있는 전체 변수 목록은 다음을 통해 얻을 수 있습니다.

rpm --querytags

의 경우 RELEASE와 같은 출력 84.el6은 정상이며 예상되는 것입니다. 실제로는 패키지별로 또는 배포 용으로 RPM 패키지가 버전 화되는 방식이기 때문입니다.


2
설치된 패키지에서만 작동합니다. 파일 이름을 조작하고 싶습니다. $ 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
TomOnTime

@TomOnTime 잠시만 기다려주십시오 ... 패키지에 실제로 무엇이 있는지 상관하지 않습니까?
Michael Hampton

4
더 빨리 알게 되길 바랍니다. RPM 도구는 패키지 내용 만 처리합니다. 파일 이름은 완전히 관련이 없습니다 (이 답변은 효과가 없습니다).
Michael Hampton

1
예를 들어 다음과 같이 재미있는 구문 분석이 있습니다.libopenssl0_9_8-32bit-0.9.8j-0.26.1_0.50.1.x86_64.delta.rpm
MikeyB

5
@TomOnTime- "설치된 패키지에서만 작동합니다"사실이 아님-세 번째 예에서 -p 옵션을 누락했습니다 : rpm --queryformat "% {NAME} % {VERSION} % {RELEASE} % {ARCH}"-qp 파일 .rpm
Sam Elstob

14

필자가 찾고있는 것을 수행하는 공식적인 방법은 Python에서 들었습니다.

from rpmUtils.miscutils import splitFilename

(n, v, r, e, a) = splitFilename(filename)

필요한 것을 수행하는 짧은 Python 프로그램을 작성했습니다. 포함을 위해 스크립트를 rpmdev 프로젝트에 제공 할 것입니다.


1
데비안 패키지 이름 지정 규칙은 매우 간단하고 훌륭합니다. rpm 세계가 어떻게 그런 혼란에 빠졌는지는 모르겠습니다. 여기에 답변에 스크립트를 붙여 넣을 수 있습니까?
Paul Hedderly

3

테스트 할 수있는 모든 데이터에 맞는 정규식을 해결했습니다. 욕심쟁이와 욕심없는 성냥을 혼합해서 사용해야했습니다. 즉, 여기 내 펄 및 파이썬 버전이 있습니다 :

펄 :

#! /usr/bin/perl

foreach (@ARGV) {
    ($path, $name, $version, $release, $platform,
      @junk) = m#(.*/)*(.*)-(.*)-(.*?)\.(.*)(\.rpm)#;
    $verrel = $version . '-' . $release;

    print join("\t", $path, $name, $verrel, $version, $rev, $platform), "\n";
}

파이썬 :

#! /usr/bin/python

import sys
import re

for x in sys.argv[1:]:
    m = re.search(r'(.*/)*(.*)-(.*)-(.*?)\.(.*)(\.rpm)', x)
    if m:
        (path, name, version, release, platform, _) = m.groups()
        path = path or ''
        verrel = version + '-' + release
        print "\t".join([path, name, verrel, version, release, platform])
    else:
        sys.stderr.write('ERROR: Invalid name: %s\n' % x)
        sys.exit(1)

오히려 RPM 프로젝트에서 나오는 정규식을 원합니다. 내가 위에서 발명 한 것은 지금해야 할 것입니다.


이것은 대부분 내 솔루션과 비슷하지만 .*실제로 일치하는 것을 제외하고는 피하십시오 . 그래도 당신이 직접 찾은 것을 보게되어 반갑습니다!
mveroone

2
파일 이름은이 정보를 얻는 나쁜 방법으로 저를 때립니다. 특정 벤더 제공 RPM 세트에서 작동 할 수 있으므로 (벤더가 타사 제품을 표준화하고 이름 형식을 변경하지 않는 한 괜찮을 수도 있지만) 창의적으로 이름이 지정된 RPM 파일이 많이 있습니다. 몇 초 전에 Adobe에서 얻은 Acrobat Reader는 ( AdbeRdr9.5.5-1_i486linux_enu.rpm)입니다. 위의 정규 표현식 구문 분석이 중단됩니다.
voretaq7

진실. 그러나 Adbe는 yum 파일 이름 표준을 위반하기 때문에 어떤 솔루션에서도 작동하지 않습니다. (기술적으로 문제는 RPM 파일 이름이 아닌 yum 파일 이름에 관한 것이어야합니다).
TomOnTime

1

Rpm 파일은 극단적 인 경우 약간의 펑키 파일 이름을 가질 수 있지만 일반적으로 NVR을 하이픈으로 분할 할 수 있습니다. catch는 NVR의 N (이름) 부분에 하이픈과 밑줄이 포함될 수 있지만 V (버전) 및 R (릴리스)에는 불필요한 하이픈이없는 것이 보장됩니다. 따라서 VR 부분을 잘라서 이름을 도출하는 것으로 시작할 수 있습니다.

$ RPM=/home/builder/packages/testing-dev/CentOS/6/x86_64/emacs-mercurial-2.8-3.el6.x86_64.rpm
$ echo ${RPM%-*-*}
/home/builder/packages/testing-dev/CentOS/6/x86_64/emacs-mercurial

이를 바탕으로 버전 및 릴리스 부분을 분리 할 수 ​​있습니다.

echo ${RPM#${RPM%-*-*}-*}
2.8-3.el6.x86_64.rpm

하이픈을 다시 분할하여 필요한 부분을 분리하십시오. 그리고 분명히 아치 및 rpm 파일 확장자 문자열을 제거하십시오. bash에서 어떻게 접근 할 수 있는지에 대한 아이디어를 제공합니다.


1

이전에 말한 것처럼 rpm에서 -q --queryformat 옵션을 사용하십시오. 설치되지 않은 패키지에서이 작업을 수행하려면 다음과 같이 -p옵션으로 rpm을 지정할 수 있습니다 .

rpm -q -p ./Downloads/polysh-0.4-1.noarch.rpm --queryformat "%{NAME} %{VERSION} %{RELEASE} %{ARCH}\n"
polysh 0.4 1 noarch

예 :

$ ls ./Downloads/*.rpm
./Downloads/adobe-release-x86_64-1.0-1.noarch.rpm
./Downloads/nautilus-dropbox-1.6.0-1.fedora.x86_64.rpm
./Downloads/playonlinux-yum-4-1.noarch.rpm
./Downloads/skype-4.2.0.11-fedora.i586.rpm
./Downloads/dbview-1.0.4-2.1.x86_64.rpm
./Downloads/openmotif22-libs-2.2.4-192.1.3.x86_64.rpm
./Downloads/polysh-0.4-1.noarch.rpm

나에게 준다

adobe-release-x86_64 1.0 1 noarch
dbview 1.0.4 2.1 x86_64
nautilus-dropbox 1.6.0 1.fc10 x86_64
openmotif22-libs 2.2.4 192.1.3 x86_64
playonlinux-yum 4 1 noarch
polysh 0.4 1 noarch
skype 4.2.0.11 fc16 i586

파일 이름을 분할하는 것이 잘못되었습니다!

for filename in """<paste list here>""".split():
    print splitFilename(filename)

('./Downloads/adobe-release-x86_64', '1.0', '1', '', 'noarch')
('./Downloads/nautilus-dropbox', '1.6.0', '1.fedora', '', 'x86_64')
('./Downloads/playonlinux-yum', '4', '1', '', 'noarch')
('./Downloads/skype', '4.2.0.11', 'fedora', '', 'i586')
('./Downloads/dbview', '1.0.4', '2.1', '', 'x86_64')
('./Downloads/openmotif22-libs', '2.2.4', '192.1.3', '', 'x86_64')
('./Downloads/polysh', '0.4', '1', '', 'noarch')

그래서 관심을 지불 ,이 예를 들어, 회전의 정확한 세부 사항 아닌 1.fedora실제로 1.fc10회전 수에서.


혼란을 봅니다. RPM이 설치되지 않았을뿐만 아니라이 시스템에는 RPM이 없습니다. 패키지 및 파일 이름 목록을 처리하고 있습니다. 리포지토리를 관리하는 것입니다. 실제 패키지가 없습니다.
TomOnTime

0

정규식 및 / 또는 Perl에 익숙한 경우 매우 쉽습니다.

 ls | head | perl -p -e 'm#([^\-]+?)-(.*).rpm$#; print "$1 $2\n";$_=""' 

또는 정규식 만 :

m#([^\-]+?)-(.*).rpm$#

분할하면 다음과 같습니다.

  • 하이픈 이외의 문자, 하나 이상의 문자 : [^\-]+(문자 그룹에서 하이픈이 특별한 의미를 갖기 때문에 이스케이프 처리됨)
  • 첫 번째 하이픈 (및 마지막이 아닌) 이후에 일치를 중지하십시오. [^\-]+?
  • 이것을 캡처 그룹에 추가하십시오. ([^\-]+?)
  • 그런 다음 하이픈 : ([^\-]+?)-
  • 그런 다음 다른 캡처 그룹의 다른 것 (그러나 후행 .rpm) : ([^\-]+?)-(.*).rpm$ (달러는 "라인 끝"을 의미합니다)
  • 실제 일치 형식보다 : m#([^\-]+?)-(.*).rpm$#

완료! 그냥 변수의 두 부분을 취득 $1하고$2

첫 번째 라이너에 대한 의견 :

나는 rpm 파일이 많은 디렉토리에 있었기 때문에 ls.

perl -p 는;

perl -e 'while(<STDIN>){ chomp($_);  [YOUR CODE HERE] ; print($_); }' 

$_압축을 풀고 사용자 정의 인쇄 한 후 펄이 인쇄되지 않도록 널 문자열을 넣어야한다고 설명 합니다. 이 작은 '핵'을 없애기 위해 대체를 사용할 수 있음에 유의하십시오.


수백 개의 RPM 이름에서는 전혀 작동하지 않습니다. 예 : module-init-tools-3.9-21.el6_4.x86_64.rpm .
Nemo

0

가장 간단한 쉘 방법은 다음과 같습니다.

ls | rev | cut -d/ -f1 | cut -d- -f3- | rev

즉, 첫 번째 부분 만 슬래시 컷을 사용하여 각 줄을 뒤집습니다. emanelif을 다음 하이픈을 모두 잘라하지만 첫 번째 두 부분 (뒤에 즉, 휴가 사용) ESAELER가 포함 TSER FO ETH emanelifNOISREV )와 역 enil의 뒷면.

예제 파일로 :

$ cat /tmp/packages.txt | rev | cut -d/ -f1 | cut -d- -f3- | rev
emacs-mercurial
emacs-mercurial-el
mercurial
mercurial-hgk
python-redis
redis
sei_dnsmaster
$

다른 부분을 얻으려면 cut (1) 을 읽으십시오 .


0

활용할 수 있습니다 dnf info . 다음은 값을 가져오고 변수로 설정하는 Bash 스크립트의 예입니다.

function dnfinfo() {
   dnf info "$(echo "${1}" | sed 's/\.rpm$//g')"
}

function splitname() {
   eval $(
     dnfinfo "${1}" | \
     grep "^Arch\|^Name\|^Release\|^Version" | \
     sort | \
     awk -F": " {'print "\""$2"\""'} | \
     tr "\n" " " | \
     awk {'print "xarch="$1"~xname="$2"~xrel="$3"~xver="$4'} | \
     tr "~" "\n"
   )
}

splitname "tcpdump-4.9.2-5.el8.x86_64.rpm"
echo "${xname} ${xver} ${xrel} ${xarch}"

패키지가 설치되지 않은 경우에도 결과가 나타납니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.