अपने घटकों में एक RPM नाम पार्स करें


19

क्या एक नाम-पार्सिंग टूल है जो आधिकारिक आरपीएम टूल पैकेज का हिस्सा है?

मेरे पास फ़ाइलनामों की एक सूची है। प्रत्येक 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) यदि नहीं, तो क्या मैं आधिकारिक रीजेक्स का उपयोग कर सकता हूं। (३) अजगर उस रेगेक्स के बराबर क्या है?

अग्रिम में धन्यवाद!


क्या आप यह स्पष्ट कर सकते हैं कि आपको अपना इनपुट कहां से मिल रहा है और यह किस प्रारूप में है।
user9517 supportGoFundMonica

जवाबों:


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 एक मिनट प्रतीक्षा करें ... तो आपको परवाह नहीं है कि पैकेज में वास्तव में क्या है?
माइकल हैम्पटन

4
काश मैं जल्दी ही यह जान लेता। RPM उपकरण केवल पैकेज सामग्री से निपटते हैं; फ़ाइल नाम पूरी तरह से अप्रासंगिक है (और यह उत्तर आपके लिए काम नहीं करेगा)।
माइकल हैम्पटन

1
उदाहरण के लिए, मज़ेदार पर्सिंग करें:libopenssl0_9_8-32bit-0.9.8j-0.26.1_0.50.1.x86_64.delta.rpm
मिकीबी

5
@TomOnTime - "यह केवल इंस्टॉल किए गए पैकेजों के साथ काम करता है" सत्य नहीं - आप तीसरे उदाहरण में -p विकल्प से चूक गए: rpm --queryformat "% {NAME}% {VERSION}% {RAILASE}% {ARP}" -qp फ़ाइल .rpm
सैम एल्स्टोब

14

मुझे आधिकारिक तरीका बताया गया है कि मैं जो चाह रहा हूं वह अजगर में है:

from rpmUtils.miscutils import splitFilename

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

मैंने एक छोटा पायथन प्रोग्राम लिखा है जो मुझे चाहिए। मैं समावेश के लिए rpmdev परियोजना को स्क्रिप्ट की पेशकश करूंगा।


1
डेबियन पैकेज के नामकरण नियम इतने सरल और स्पष्ट हैं - मुझे नहीं पता कि आरपीएम दुनिया इस तरह की गड़बड़ी में कैसे समाप्त हो गई है। क्या आप यहाँ उत्तर में अपनी स्क्रिप्ट चिपका सकते हैं?
पॉल हैदरली

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)

मैं आरजेएम प्रोजेक्ट से आता है। जो मैंने ऊपर आविष्कार किया था, उसे अब करना होगा।


यह ज्यादातर मेरे समाधान के समान है (लेकिन .*जब तक आप वास्तव में कुछ भी मिलान नहीं करना चाहते हैं) से बचें । यह देखकर अच्छा लगा कि आप अपने आप से मिल गए, हालांकि!
मेवरोन

2
फ़ाइल नाम मुझे इस जानकारी को प्राप्त करने के लिए एक बुरे तरीके से प्रभावित करता है। यह विक्रेता द्वारा प्रदान किए गए RPM के एक विशिष्ट सेट के लिए काम कर सकता है (इसलिए आप तब तक ठीक हो सकते हैं जब तक आपका विक्रेता तृतीय-पक्ष सामान मानकीकृत करता है और कभी भी उनका नामकरण प्रारूप नहीं बदलता है), लेकिन मैंने रचनात्मक रूप से नामित RPM फ़ाइलों को बहुत देखा है। एक्रोबेट रीडर AdbeRdr9.5.5-1_i486linux_enu.rpmजिसे मैंने कुछ सेकंड पहले Adobe से पकड़ा था ) जो आपके regex को पार्स करता है।
voretaq7

सच। लेकिन Adbe किसी भी समाधान के लिए काम नहीं करेगा क्योंकि यह yum फ़ाइल नाम मानक को तोड़ता है। (तकनीकी रूप से सवाल yum filenames के बारे में होना चाहिए, RPM फाइलनाम के बारे में नहीं)।
टॉमऑनटाइम

1

आरपीएम फाइलें चरम मामलों में कुछ फंकी फाइल नाम रख सकती हैं, लेकिन आम तौर पर आप एनवीआर को हाइफ़न पर विभाजित कर सकते हैं। एनवीआर का एन (नाम) हिस्सा है पकड़ में हाइफ़न और अंडरस्कोर हो सकते हैं, लेकिन वी (संस्करण) और आर (रिलीज़) की गारंटी है कि किसी भी बाहरी हाइफ़न की आवश्यकता नहीं है। तो आप एक नाम प्राप्त करने के लिए वीआर भाग को बंद करके शुरू कर सकते हैं।

$ 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

जिस हिस्से में आपको ज़रूरत है उसे अलग करने के लिए बस हाइफ़न को फिर से विभाजित करें। और स्पष्ट रूप से आर्क और आरपीएम फाइल एक्सटेंशन स्ट्रिंग्स को साफ करें, जो कि एक दिया गया है। बस आपको इस बात का अंदाजा है कि यह कैसे बैश में आ सकता है।


1

Rpm से .q --queryformat विकल्पों का उपयोग करें जैसा कि पहले कहा गया था, यदि आप एक गैर स्थापित पैकेज पर ऐसा करना चाहते हैं तो आप rpm को -pविकल्प के साथ निर्दिष्ट कर सकते हैं , जैसे:

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 स्थापित नहीं है, मेरे पास इस मशीन पर नहीं है। मैं पैकेज और फ़ाइल नामों की सूची संसाधित कर रहा हूं। यह ऐसी चीज़ के लिए है जो रेपो इन्वेंट्री का प्रबंधन करता है; इसमें वास्तविक पैकेज नहीं है।
टॉमऑन टाइम

0

यदि आप रेगुलर एक्सप्रेशन और / या पर्ल से परिचित हैं, तो यह काफी आसान है।

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

या अकेले रेगेक्स:

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

यदि आप इसे विभाजित करते हैं:

  • कम से कम एक चरित्र के अलावा कुछ भी नहीं: [^\-]+(बच गए क्योंकि हाइफन का चरित्र समूहों में एक विशेष अर्थ है)
  • पहली हाइफ़न (और अंतिम नहीं) के बाद मैच रोकें: [^\-]+?
  • इसे कैप्चर ग्रुप में जोड़ें: ([^\-]+?)
  • फिर एक हाइफ़न: ([^\-]+?)-
  • फिर एक और कब्जा समूह (लेकिन अनुगामी .rpm) में कुछ और : ([^\-]+?)-(.*).rpm$ (डॉलर का अर्थ है "पंक्ति का अंत")
  • एक व्यावहारिक मिलान प्रारूप की तुलना में संलग्न करें: m#([^\-]+?)-(.*).rpm$#

किया हुआ ! बस चर में दोनों भागों $1और$2

पहले एक-लाइनर पर टिप्पणी:

मैं कई आरपीएम फाइलों के साथ एक निर्देशिका में था, इसलिए ls

perl -p के बराबर है ;

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

जो समझाते हैं कि मुझे $_निकालने के बाद पर्ल को वापस खींचने से बचने के लिए एक नल-स्ट्रिंग डालनी थी और इसे कस्टम-प्रिंट किया। ध्यान दें कि मैं इस छोटी सी 'हैक' को जोड़ने के लिए प्रतिस्थापन का उपयोग कर सकता था।


यह RPM के सैकड़ों नामों पर बिल्कुल भी काम नहीं करता है, जैसे module-init-tools-3.9-21.el6_4.x86_64.rpm
निमो

0

IMHO सबसे सरल शेल तरीका है:

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

यह है: प्रत्येक पंक्ति को उल्टा करें, स्लैश कट का उपयोग करते हुए सिर्फ पहला भाग ( इमानेलिफ़ ), फिर हाइफ़न कट का उपयोग करके, लेकिन पहले दो भागों (यानी एमैनियर पीछे छोड़ दें जिसमें एमैनलिफ़ एथ फ़ॉस् टसर और एनओएसआरईवी शामिल हैं ) और पीछे की ओर उल्टा करें ।

अपनी उदाहरण फ़ाइल के साथ:

$ 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
$

अन्य भागों को प्राप्त करने के लिए कट (1) पढ़ने पर जोर दिया जाता है ।


0

आप उपयोग कर सकते हैं dnf info। मूल्यों को प्राप्त करने और एक चर के रूप में सेट करने के लिए यहां एक उदाहरण बैश स्क्रिप्ट है:

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}"

पैकेज स्थापित नहीं होने पर भी यह एक परिणाम देगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.