पर्ल में रेगेक्स के साथ पार्सिंग विशेषताएँ

यहां एक समस्या है जिसे मैंने हाल ही में भाग लिया था। मेरे पास फॉर्म के स्ट्रिंग्स हैं

"x=1 and y=abc and z=c4g and ..."

कुछ विशेषताओं में संख्यात्मक मान होते हैं, कुछ में अल्फा मान होते हैं, कुछ मिश्रित होते हैं, कुछ में तिथियां होती हैं आदि।

शुरुआत में प्रत्येक स्ट्रिंग माना " x = someval और y = anotherval " है, लेकिन कुछ नहीं। मेरे पास तीन चीजें हैं जो मुझे करने की ज़रूरत है।

  1. स्ट्रिंग को यह सुनिश्चित करने के लिए मान्य करें कि उनके पास x और y है।
  2. वास्तव में x और y के मानों को पार्स करें।
  3. शेष स्ट्रिंग प्राप्त करें।

शीर्ष पर दिए गए उदाहरण को देखते हुए, इसके परिणामस्वरूप निम्नलिखित चर आएंगे:

$x = 1;
$y = "abc";
$remainder = "z=c4g and ..."

मेरा सवाल है: क्या इन और को एक नियमित अभिव्यक्ति के साथ मान्य करने के लिए एक (उचित) सरल तरीका है? अर्थात।:

if ($str =~ /someexpression/)
{
    $x = $1;
    $y = $2;
    $remainder = $3;
}

ध्यान दें कि स्ट्रिंग में केवल x और y विशेषताएँ हो सकती हैं। यह एक वैध स्ट्रिंग है।

मैं अपना समाधान एक उत्तर के रूप में पोस्ट करूंगा, लेकिन यह मेरी एकल-रेगेक्स वरीयता को पूरा नहीं करता है।

0
ro fr bn

5 उत्तर

मैं नियमित अभिव्यक्तियों में सबसे अच्छा नहीं हूं, लेकिन यह आप जो खोज रहे हैं उसके करीब है:

/x=(.+) and y=([^ ]+)( and (.*))?/

सिवाय आप $ 1, $ 2, और $ 4 का उपयोग करते हैं। उपयोग में:

my @strs = ("x=1 and y=abc and z=c4g and w=v4l",
            "x=yes and y=no",
            "z=nox and w=noy");

foreach (@strs) {
    if ($_ =~ /x=(.+) and y=([^ ]+)( and (.*))?/) {
        $x = $1;
        $y = $2;
        $remainder = $4;
        print "x: $x; y: $y; remainder: $remainder\n";
    } else {
        print "Failed.\n";
    }
}

आउटपुट:

x: 1; y: abc; remainder: z=c4g and w=v4l
x: yes; y: no; remainder: 
Failed.

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

0
जोड़ा

यहां मूल रूप से मैंने इसे हल करने के लिए क्या किया है:

($x_str, $y_str, $remainder) = split(/ and /, $str, 3);

if ($x_str !~ /x=(.*)/)
{
    # error
}

$x = $1;

if ($y_str !~ /y=(.*)/)
{
    # error
}

$y = $1;

मैंने कुछ अतिरिक्त सत्यापन और त्रुटि प्रबंधन को छोड़ दिया है। यह तकनीक काम करती है, लेकिन यह उतनी संक्षिप्त या सुंदर नहीं है जितनी मुझे पसंद आएगी। मुझे आशा है कि किसी के पास मेरे लिए बेहतर सुझाव होगा।

0
जोड़ा
यह मुझे "सभी नियमों पर शासन करने के लिए एक regexp" की तुलना में सरल और अधिक रखरखाव लगता है। मैं शायद x = और y = से मेल खाने के लिए theregexps की शुरुआत में एक ^ जोड़ सकता हूं ताकि केस not_x = ... या इसी तरह से बच सके। आप एक एकल regexp क्यों चाहते हैं?
जोड़ा लेखक mirod, स्रोत

रुड और सेबजेर ने आपको सबसे अधिक तरीके से प्राप्त किया है लेकिन दोनों को कुछ समस्याएं हैं:

रुड ने सुझाव दिया:

/x = (। +) और y = ([^] +) (और (। *))?/

सेबजेर ने इसे संशोधित किया:

/^ x = (। +) और y = ([^] +) (?: और (। *))?/

दूसरा संस्करण बेहतर है क्योंकि यह "x = foo" के साथ "not_x = foo" को भ्रमित नहीं करेगा, लेकिन "x = foo z = bar y = baz" जैसी चीज़ों को स्वीकार करेगा और $ 1 = "foo z = bar" सेट करेगा अवांछनीय।

यह शायद आप जो खोज रहे हैं:

/^ x = (\ w +) और y = (\ w +) (?: और (। *))?/

यह x = और y = विकल्पों, स्थानों और अनुमतियों और वैकल्पिक "और ..." के बीच कुछ भी अस्वीकार करता है जो $ 3 में होगा

0
जोड़ा

मान लीजिए कि आप दूसरे नाम = मूल्य जोड़ों के साथ कुछ भी करना चाहते हैं, इस तरह मैं इसे कैसे करूंगा (पर्ल संस्करण 5.10 का उपयोग करके):

use 5.10.0;
use strict;
use warnings;

my %hash;
while(
    $string =~ m{
       (?: ^ | \G )    # start of string or previous match
       \s*

       (?   \w+ ) # word characters
       =
       (? \S+ ) # non spaces

       \s*             # get to the start of the next match
       (?: and )?
    }xgi
){
    $hash{$+{key}} = $+{value};
}

# to make sure that x & y exist
die unless exists $hash{x} and exists $hash{y};

पुराने पर्ल पर (कम से कम पर्ल 5.6);

use strict;
use warnings;

my %hash;
while(
    $string =~ m{
       (?: ^ | \G )   # start of string or previous match
       \s*

       ( \w+ ) = ( \S+ )

       \s*            # get to the start of the next match
       (?: and )?
    }xgi
){
    $hash{$1} = $2;
}

# to make sure that x & y exist
die unless exists $hash{x} and exists $hash{y};

यदि आपको अधिक डेटा के साथ काम करने की आवश्यकता है तो इन्हें काम जारी रखने का अतिरिक्त लाभ है।

0
जोड़ा
\ G पहले से ही स्ट्रिंग की शुरुआत से मेल खाता है, इसलिए आप (?: ^ | \ G) को \ G से प्रतिस्थापित कर सकते हैं। लेकिन शुरुआत में कारक में \ G डालने का एक बेहतर तरीका है और शुरुआत में और को स्थानांतरित करना है: \ G (?: ^ | \ S + और \ s +) (\ w +) = (\ S +)
जोड़ा लेखक Casimir et Hippolyte, स्रोत
नाम कैप्चर बफर का अच्छा उदाहरण +1 करें!
जोड़ा लेखक Ben Deutsch, स्रोत

रुड के संस्करण में काफी सरल संशोधन के रूप में,

/^x=(.+) and y=([^ ]+)(?: and (.*))?/

आपको $ 1, $ 2 और $ 3 (?: इसे एक गैर-कैप्चरिंग समूह बनाता है) का उपयोग करने की अनुमति देगा, और यह सुनिश्चित करेगा कि "not_x =" मिलान करने की अनुमति देने के बजाय स्ट्रिंग "x =" से शुरू होती है

यदि आपके पास एक्स और वाई मानों के बारे में बेहतर जानकारी है, तो इसका उपयोग रेगेक्स को और कसने के लिए किया जाना चाहिए:

my @strs = ("x=1 and y=abc and z=c4g and w=v4l",
        "x=yes and y=no",
        "z=nox and w=noy",
        "not-x=nox and y=present",
        "x=yes and w='there is no and y=something arg here'");

foreach (@strs) {
    if ($_ =~ /^x=(.+) and y=([^ ]+)(?: and (.*))?/) {
        $x = $1;
        $y = $2;
        $remainder = $3;
        print "x: {$x}; y: {$y}; remainder: {$remainder}\n";
    } else {
        print "$_ Failed.\n";
    }
}

आउटपुट:

x: {1}; y: {abc}; remainder: {z=c4g and w=v4l}
x: {yes}; y: {no}; remainder: {}
z=nox and w=noy Failed.
not-x=nox and y=present Failed.
x: {yes and w='there is no}; y: {something}; remainder: {}

ध्यान दें कि अंतिम परीक्षण का गुम हिस्सा वाई परीक्षण के वर्तमान संस्करण के कारण है, जिसमें कोई रिक्त स्थान नहीं है, यदि एक्स टेस्ट में एक ही प्रतिबंध था कि स्ट्रिंग विफल हो गई थी।

0
जोड़ा