मेरे पास एक स्ट्रिंग है जिसे मुझे पार्स करने की आवश्यकता है। यह निम्नलिखित आवश्यकताओं को पूरा करता है:

  • इसमें 0 या अधिक कुंजी-> मान जोड़े शामिल हैं।
  • कुंजी हमेशा 2 अक्षर होती है।
  • मान एक या अधिक संख्या है।
  • कुंजी और मान के बीच कोई स्थान नहीं होगा।
  • अलग-अलग जोड़ियों के बीच जगह हो भी सकती है और नहीं भी।

उदाहरण तार मैं देख सकता हूँ:

  • AB1234 // एक कुंजी-> मान जोड़ी (कुंजी = AB, मान = 1234)
  • AB1234 BC2345 // दो कुंजी-> मूल्य जोड़े, अंतरिक्ष द्वारा अलग किए गए
  • AB1234BC2345 // दो कुंजी-> मान जोड़े, जो अंतरिक्ष से अलग नहीं होते हैं
  • // खाली स्टिंग, कोई कुंजी नहीं-> मूल्य जोड़े
  • AB12345601BC1234CD1232PE2343 // बहुत सारी कुंजी-> मूल्य जोड़े, कोई स्थान नहीं
  • AB12345601 BC1234 CD1232 PE2343 // बहुत सारी कुंजी-> रिक्त स्थान के साथ मूल्य जोड़े

मुझे इस स्ट्रिंग का एक पर्ल हैश बनाने की जरूरत है। अगर मैं गारंटी दे सकता हूं कि यह 1 जोड़ी है तो मैं ऐसा कुछ करूंगा:

$string =~ /([A-Z][A-Z])([0-9]+)/
$key = $1
$value = $2
$hash{$key} = $value

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

काश मेरे पास इससे निपटने के लिए इतना भद्दा डेटा स्रोत नहीं होता-

जोनाथन

4
Jonathan 26 नवम्बर 2011, 02:57

3 जवाब

सबसे बढ़िया उत्तर

वैश्विक ध्वज के साथ सूची संदर्भ में, एक रेगेक्स all लौटाएगा मेल खाने वाले सबस्ट्रिंग:

use Data::Dumper;

@strs = (
    'AB1234',
    'AB1234 BC2345',
    'AB1234BC2345',
    '',
    'AB12345601BC1234CD1232PE2343',
    'AB12345601 BC1234 CD1232 PE2343'
);

for $str (@strs) {
    # The money line
    %parts = ($str =~ /([A-Z][A-Z])(\d+)/g);

    print Dumper(\%parts);
}

अधिक अस्पष्टता के लिए, पैटर्न से मेल खाने वाले कोष्ठकों को हटा दें: %parts = $str =~ /([A-Z][A-Z])(\d+)/g;

8
outis 26 नवम्बर 2011, 03:09

आप पहले से ही हैं:

$hash{$1} = $2 while $string =~ /([[:alpha:]]{2})([0-9]+)/g
3
choroba 26 नवम्बर 2011, 03:05

यह मानते हुए कि आपके तार निश्चित रूप से आपकी योजना से मेल खाने वाले हैं (अर्थात A122 या ABC123) के कोई तार नहीं होंगे, तो यह काम करना चाहिए:

my @strings = ( 'AB1234', 'AB1234 BC2345', 'AB1234BC2345' );

foreach my $string (@strings) {
    $string =~ s/\s+//g;
    my ( $first, %elems ) = split(/([A-Z]{2})/, $string);
    while (my ($key,$value) = each %elems) {
        delete $elems{$key} unless $key =~ /^[A-Z]{2}$/;
        delete $elems{$key} unless $value =~ /^\d{4}$/;
    }
    print Dumper \%elems;
}
0
CanSpice 26 नवम्बर 2011, 03:09
शुद्ध रेगेक्स उत्तर थोड़ा साफ दिखते हैं। मैं बस split के साथ कुछ अलग करने की कोशिश कर रहा था। :-)
 – 
CanSpice
26 नवम्बर 2011, 03:10
यदि यह सब एक स्ट्रिंग में आता है तो आप कुछ ऐसा कर सकते हैं $string =~ s/\s+//g; my %h = map{split/(?<=\D)(?=\d)/}split/(?<=\d)(?=\D)/, $string;
 – 
flesk
26 नवम्बर 2011, 03:30
या बस %h = split /\s*(\d+)\s*/, $string
 – 
TLP
26 नवम्बर 2011, 06:02