2010-07-08 10 views
11

में आरपीएम संस्करणों की तुलना कैसे करूं मैं यह जानने का प्रयास कर रहा हूं कि मैं आरपीएमएस की 2 सूचियों (वर्तमान में स्थापित) की तुलना कैसे कर सकता हूं और (स्थानीय भंडार में उपलब्ध) की तुलना कैसे कर सकता हूं और देख सकता हूं कि कौन से आरपीएमएस पुराने हैं। मैं रेगेक्स के साथ झुका रहा हूं लेकिन आरपीएमएस के लिए कई अलग-अलग नामकरण मानक हैं जिनके साथ मुझे काम करने के लिए अच्छी सूची नहीं मिल सकती है। मेरे पास मेरे ड्राइव पर वास्तविक आरपीएमएस नहीं है इसलिए मैं rpm -qif नहीं कर सकता।मैं पाइथन

pattern1 = re.compile(r'^([a-zA-Z0-9_\-\+]*)-([a-zA-Z0-9_\.]*)-([a-zA-Z0-9_\.]*)\.(.*)') 
for rpm in listOfRpms: 
    packageInfo = pattern1.search(rpm[0]).groups() 
    print packageInfo 

यह एक विशाल बहुमत के लिए काम करता है, लेकिन सभी (2300/2400)

yum-metadata-parser-1.1.2-2.el5 
('yum-metadata-parser', '1.1.2', '2', 'el5') **What I need 

लेकिन कोई भी उदाहरण के लिए इन काम जब तक कि मैं कुछ अन्य लोगों कि पहले भी काम को तोड़ने ..

  • wvdial-1.54.0-3
  • xdelta-1.1.3-20
  • xdelta-1.1.3-20_2
  • xmlsec1-1.2.6-3
  • xmlsec1-1.2.6-3_2
  • ypbind-1.17.2-13
  • ypbind-1.17.2-8
  • ypserv-2.13-14
  • जिप-2.3-27
  • zlib-1.2.3-3
  • zlib-1.2.3-3_2
  • zsh-4.2.6-1
+0

आप आरपीएम की सूची कैसे प्राप्त कर रहे हैं? – Craig

उत्तर

14

आरपीएम पैरालांस में, 2.el5 रिलीज फ़ील्ड है; 2 और el5 अलग फ़ील्ड नहीं हैं। हालांकि, आपके उदाहरणों के अनुसार रिलीज में . की आवश्यकता नहीं है। एक शॉट में रिलीज फ़ील्ड को कैप्चर करने के लिए अंत में \.(.*) ड्रॉप करें।

तो अब आपके पास पैकेज का नाम, संस्करण और रिलीज़ है।

import rpm 
# t1 and t2 are tuples of (version, release) 
def compare(t1, t2): 
    v1, r1 = t1 
    v2, r2 = t2 
    return rpm.labelCompare(('1', v1, r1), ('1', v2, r2)) 

क्या कि अतिरिक्त '1', आप से पूछना है: उनकी तुलना करने के लिए सबसे आसान तरीका आरपीएम के अजगर मॉड्यूल का उपयोग करने के लिए है? यह युग है, और यह अन्य संस्करण तुलना विचारों को ओवरराइड करता है। इसके अलावा, यह आमतौर पर फ़ाइल नाम में उपलब्ध नहीं है। यहां, हम इस अभ्यास के प्रयोजनों के लिए इसे '1' पर ले जा रहे हैं, लेकिन यह बिल्कुल सटीक नहीं हो सकता है। यदि आप अकेले फ़ाइल नामों से जा रहे हैं तो यह दो कारणों में से एक है कि आपका तर्क बंद होने जा रहा है।

अन्य कारण यह है कि आपका तर्क rpm से अलग हो सकता है Obsoletes फ़ील्ड है, जो किसी पैकेज को पूरी तरह से अलग नाम के साथ पैकेज में अपग्रेड करने की अनुमति देता है। यदि आप इन सीमाओं के साथ ठीक हैं, तो आगे बढ़ें।

आप हाथ में rpm अजगर पुस्तकालय नहीं है, तो, यहाँ rpm 4.4.2.3 के रूप में जारी, संस्करण, और युग में से प्रत्येक की तुलना के लिए तर्क दिया गया है:

  • वर्णमाला क्षेत्रों [a-zA-Z]+ और संख्यात्मक फ़ील्ड के लिए प्रत्येक स्ट्रिंग खोजें [0-9]+ जंक [^a-zA-Z0-9]* द्वारा अलग किया गया।
  • प्रत्येक स्ट्रिंग में लगातार फ़ील्ड एक दूसरे से तुलना की जाती हैं।
  • वर्णमाला अनुभागों की तुलना लेक्सिकोोग्राफ़िक रूप से की जाती है, और संख्यात्मक वर्गों की तुलनात्मक रूप से की जाती है।
  • मिस्चैच के मामले में जहां एक फ़ील्ड संख्यात्मक है और एक वर्णमाला है, संख्यात्मक क्षेत्र हमेशा अधिक (नया) माना जाता है।
  • ऐसे मामले में जहां एक स्ट्रिंग फ़ील्ड से बाहर हो जाती है, दूसरे को हमेशा अधिक (नया) माना जाता है।

गोरी विवरण के लिए आरपीएम स्रोत में lib/rpmvercmp.c देखें।

+0

बहुत धन्यवाद ओवेन एस। मैं पहले आरपीएम पायथन मॉड्यूल में देख रहा था लेकिन इसे खारिज कर दिया क्योंकि मैंने सोचा था कि यह केवल आरपीएम डेटाबेस के साथ बातचीत करता है। एक जादू की तरह काम करता है! मेरे पास केवल फाइल नाम हैं क्योंकि मैं एक जेनोस सर्वर से आरपीएम की एक सूची खींच रहा हूं और इसे स्थानीय दर्पण पर एक सूची में तुलना कर रहा हूं। Obsoletes मेरे लिए एक आवश्यकता नहीं है। – Adam

+1

इसके लिए धन्यवाद!मैंने आपके एल्गोरिदम के विवरण को शुद्ध पाइथन फॉलबैक में http://stackoverflow.com/a/42967591/597742 में परिवर्तित कर दिया – ncoghlan

0

एक बहुत सरल regex /^(.+)-(.+)-(.+).(.+).rpm$/ है

मैं पर किसी भी प्रतिबंध के बारे में पता नहीं कर रहा हूँ पैकेज का नाम (पहला कैप्चर)। संस्करण और रिलीज पर केवल प्रतिबंध ही हैं कि उनमें '-' शामिल नहीं है। इसे कोड करने की कोई आवश्यकता नहीं है, क्योंकि अनगिनत 'उन क्षेत्रों को अलग करते हैं, इस प्रकार यदि किसी के पास' - 'होता है तो इसे विभाजित किया जाएगा और एक भी फील्ड नहीं होगा, परिणामी कैप्चर में' - ' । केवल पहला कैप्चर, नाम, में कोई भी '-' है क्योंकि यह पहले सभी अपर्याप्त '-' का उपभोग करता है।

फिर, आर्किटेक्चर है, जो इस रेगेक्स आर्किटेक्चर नाम पर कोई प्रतिबंध नहीं लेता है, सिवाय इसके कि इसमें '।' शामिल नहीं है।

कब्जा परिणाम [नाम, संस्करण, रिहाई, मेहराब]

आरपीएम नाम पर निर्भर के बारे में ओवेन के जवाब से चेतावनियां अकेले अब भी लागू होते हैं।

0

आरपीएम में पाइथन बाइंडिंग है, जो आपको rpmUtils.miscutils.compareEVR का उपयोग करने देती है। टुपल के पहले और तीसरे तर्क पैकेज नाम और पैकेजिंग संस्करण हैं। बीच संस्करण है। नीचे दिए गए उदाहरण में, मैं यह पता लगाने की कोशिश कर रहा हूं कि 3.7.4 ए को क्रमबद्ध किया गया है।

[[email protected] ~]# python 
Python 2.4.3 (#1, Dec 10 2010, 17:24:35) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-50)] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import rpmUtils.miscutils 
>>> rpmUtils.miscutils.compareEVR(("foo", "3.7.4", "1"), ("foo", "3.7.4", "1")) 
0 
>>> rpmUtils.miscutils.compareEVR(("foo", "3.7.4", "1"), ("foo", "3.7.4a", "1")) 
-1 
>>> rpmUtils.miscutils.compareEVR(("foo", "3.7.4a", "1"), ("foo", "3.7.4", "1")) 
1 
2

यहाँ एक काम rpmdevtools पैकेज से rpmdev-vercmp के आधार पर कार्यक्रम है। आपको काम करने के लिए विशेष स्थापित कुछ भी नहीं चाहिए लेकिन yum (जो rpmUtils.miscutils पायथन मॉड्यूल प्रदान करता है)।

अन्य उत्तर से अधिक लाभ आप जैसे यह पूर्ण आरपीएम नाम-संस्करण तार फ़ीड, कुछ भी बाहर पार्स करने के लिए की आवश्यकता नहीं है:

$ ./rpmcmp.py bash-3.2-32.el5_9.1 bash-3.2-33.el5.1 
0:bash-3.2-33.el5.1 is newer 
$ echo $? 
12 

बाहर निकलें स्थिति 11 पहले एक नए, 12 का मतलब है मतलब दूसरा दूसरा नया है।

#!/usr/bin/python 

import rpm 
import sys 
from rpmUtils.miscutils import stringToVersion 

if len(sys.argv) != 3: 
    print "Usage: %s <rpm1> <rpm2>" 
    sys.exit(1) 

def vercmp((e1, v1, r1), (e2, v2, r2)): 
    return rpm.labelCompare((e1, v1, r1), (e2, v2, r2)) 

(e1, v1, r1) = stringToVersion(sys.argv[1]) 
(e2, v2, r2) = stringToVersion(sys.argv[2]) 

rc = vercmp((e1, v1, r1), (e2, v2, r2)) 
if rc > 0: 
    print "%s:%s-%s is newer" % (e1, v1, r1) 
    sys.exit(11) 

elif rc == 0: 
    print "These are equal" 
    sys.exit(0) 

elif rc < 0: 
    print "%s:%s-%s is newer" % (e2, v2, r2) 
    sys.exit(12) 
1

ओवेन एस उत्तम जवाब के आधार पर, मैं एक साथ एक टुकड़ा यदि उपलब्ध प्रणाली आरपीएम बाइंडिंग का उपयोग करता है डाल, लेकिन अन्यथा एक regex आधारित अनुकरण करने के लिए वापस गिर जाता है:

try: 
    from rpm import labelCompare as _compare_rpm_labels 
except ImportError: 
    # Emulate RPM field comparisons 
    # 
    # * Search each string for alphabetic fields [a-zA-Z]+ and 
    # numeric fields [0-9]+ separated by junk [^a-zA-Z0-9]*. 
    # * Successive fields in each string are compared to each other. 
    # * Alphabetic sections are compared lexicographically, and the 
    # numeric sections are compared numerically. 
    # * In the case of a mismatch where one field is numeric and one is 
    # alphabetic, the numeric field is always considered greater (newer). 
    # * In the case where one string runs out of fields, the other is always 
    # considered greater (newer). 

    import warnings 
    warnings.warn("Failed to import 'rpm', emulating RPM label comparisons") 

    try: 
     from itertools import zip_longest 
    except ImportError: 
     from itertools import izip_longest as zip_longest 

    _subfield_pattern = re.compile(
     r'(?P<junk>[^a-zA-Z0-9]*)((?P<text>[a-zA-Z]+)|(?P<num>[0-9]+))' 
    ) 

    def _iter_rpm_subfields(field): 
     """Yield subfields as 2-tuples that sort in the desired order 

     Text subfields are yielded as (0, text_value) 
     Numeric subfields are yielded as (1, int_value) 
     """ 
     for subfield in _subfield_pattern.finditer(field): 
      text = subfield.group('text') 
      if text is not None: 
       yield (0, text) 
      else: 
       yield (1, int(subfield.group('num'))) 

    def _compare_rpm_field(lhs, rhs): 
     # Short circuit for exact matches (including both being None) 
     if lhs == rhs: 
      return 0 
     # Otherwise assume both inputs are strings 
     lhs_subfields = _iter_rpm_subfields(lhs) 
     rhs_subfields = _iter_rpm_subfields(rhs) 
     for lhs_sf, rhs_sf in zip_longest(lhs_subfields, rhs_subfields): 
      if lhs_sf == rhs_sf: 
       # When both subfields are the same, move to next subfield 
       continue 
      if lhs_sf is None: 
       # Fewer subfields in LHS, so it's less than/older than RHS 
       return -1 
      if rhs_sf is None: 
       # More subfields in LHS, so it's greater than/newer than RHS 
       return 1 
      # Found a differing subfield, so it determines the relative order 
      return -1 if lhs_sf < rhs_sf else 1 
     # No relevant differences found between LHS and RHS 
     return 0 


    def _compare_rpm_labels(lhs, rhs): 
     lhs_epoch, lhs_version, lhs_release = lhs 
     rhs_epoch, rhs_version, rhs_release = rhs 
     result = _compare_rpm_field(lhs_epoch, rhs_epoch) 
     if result: 
      return result 
     result = _compare_rpm_field(lhs_version, rhs_version) 
     if result: 
      return result 
     return _compare_rpm_field(lhs_release, rhs_release) 

ध्यान दें कि मैं हेवन टी ने सी स्तर के कार्यान्वयन के साथ स्थिरता के लिए इसका व्यापक रूप से परीक्षण किया - मैं केवल इसे फ़ॉलबैक कार्यान्वयन के रूप में उपयोग करता हूं जो कि कम से कम पर्याप्त है, ताकि एंटीना के टेस्ट सूट को उन वातावरणों में पारित किया जा सके जहां सिस्टम आरपीएम बाइंडिंग उपलब्ध नहीं हैं।

संबंधित मुद्दे