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である必要があります)

(1)rpmdevパッケージにこれを正しく行うツールがあるかどうか疑問に思っています。(2)そうでない場合、使用できる公式の正規表現はありますか。(3)その正規表現に相当するpythonは何ですか?

前もって感謝します!


どこから入力を取得しているのか、それが必要な形式を明確にしてください。
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

の場合、これは実際にRPMパッケージがディストリビューションによってパッケージ化されたとき、またはディストリビューションのためにバージョン管理される方法であるためRELEASE、出力84.el6は正常で期待されることに注意してください。


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少々お待ちください...それでは、実際にパッケージに何が入っているか気にしませんか?
マイケルハンプトン

4
もっと早く知りたいと思います。RPMツールはパッケージの内容のみを処理します。ファイル名は完全に無関係です(そして、この答えはあなたのために機能しません)。
マイケルハンプトン

1
たとえば、構文解析を楽しんでくださいlibopenssl0_9_8-32bit-0.9.8j-0.26.1_0.50.1.x86_64.delta.rpm
。– MikeyB

5
@TomOnTime-「インストールされたパッケージでのみ動作する」trueではない-3番目の例で-pオプションを見逃した:rpm --queryformat "%{NAME}%{VERSION}%{RELEASE}%{ARCH}" -qpファイル.rpm
サムエルストブ

14

私が求めていることを行う公式の方法はPythonであると言われています:

from rpmUtils.miscutils import splitFilename

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

必要なことを行う短いPythonプログラムを作成しました。含めるスクリプトをrpmdevプロジェクトに提供します。


1
Debianパッケージの命名規則はとてもシンプルでわかりやすいものです-rpmの世界がこのような混乱にどのように終わったのかはわかりません。スクリプトを回答に貼り付けてください。
ポールヘダーリー16

3

テストできるすべてのデータに適合する正規表現を作成しました。貪欲なマッチと貪欲でないマッチの混合を使用しなければなりませんでした。とはいえ、ここに私のperlとpythonのバージョンがあります:

Perl:

#! /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";
}

Python:

#! /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セットで機能する場合があります(したがって、ベンダーがサードパーティのものを標準化し、ネーミングフォーマットを変更しない限り問題ありません)。数秒前にAdobeから入手したAcrobat ReaderはAdbeRdr9.5.5-1_i486linux_enu.rpm)で、上記の正規表現解析を中断します。
voretaq7

本当です。しかし、Adbeはyumファイル名の標準に違反するため、どのソリューションでも機能しません。(技術的には、RPMファイル名ではなく、yumファイル名に関する質問である必要があります)。
-TomOnTime

1

極端な場合、RPMファイルにはファンキーなファイル名が含まれる場合がありますが、通常はNVRをハイフンで分割できます。キャッチは、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

ハイフンをもう一度分割して、必要な部分を分離します。そして明らかに、archおよび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$#

それを分割する場合:

  • ハイフン以外の少なくとも1文字:([^\-]+ハイフンは文字グループで特別な意味を持つため、エスケープされます)
  • 最初のハイフンの後に(最後ではなく)マッチを停止します: [^\-]+?
  • これをキャプチャグループに追加します。 ([^\-]+?)
  • それからハイフン: ([^\-]+?)-
  • 次に、別のキャプチャグループ内のその他のもの(ただし末尾は.rpm):(([^\-]+?)-(.*).rpm$ ドルは「行末」を意味します)
  • 実際のマッチング形式よりも囲む: m#([^\-]+?)-(.*).rpm$#

できた!変数で両方の部分を取得し$1$2

最初のワンライナーに関するコメント:

私は多くのrpmファイルがあるディレクトリにいたので、ls

perl -p に等しい;

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

これ$_は、抽出してカスタム印刷した後、perlが行を印刷しないようにするためにヌル文字列を挿入する必要があることを説明しています。この小さな「ハック」をaoidに置き換えることができたことに注意してください。


これは、数百のRPM名ではまったく機能しませんmodule-init-tools-3.9-21.el6_4.x86_64.rpm
ニモ14年

0

私見の最も簡単なシェルの方法は次のとおりです。

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

すなわち:スラッシュカットだけ最初の部分(使用して、各ラインを逆emanelifハイフンカットすべてが、最初の2つの部分を使用して、その後に)、(後ろすなわち休暇ESAELER含むemanelif ETH FO TSERNOISREVを)およびリバース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.