2012-08-07 8 views
11

में रेगेक्स का आत्मनिरीक्षण कैसे करें मैं कुछ कोड पर काम कर रहा हूं जिसे किसी भी रेगेक्स झंडे सहित पर्ल रेगेक्स को क्रमबद्ध करने की आवश्यकता है। झंडे का केवल एक सबसेट समर्थित है, इसलिए मुझे पता लगाना चाहिए कि /u जैसे असमर्थित झंडे regex ऑब्जेक्ट में हैं।पर्ल एपीआई

कोड के वर्तमान संस्करण इस करता है:

static void serialize_regex_flags(buffer *buf, SV *sv) { 
    char flags[] = {0,0,0,0,0,0}; 
    unsigned int i = 0, f = 0; 
    STRLEN string_length; 
    char *string = SvPV(sv, string_length); 

तब मैन्युअल string चार-दर-चार झंडे लगाने के लिए संसाधित करता है।

समस्या यह है कि रेगेक्स झंडे की स्ट्रिंगफिकेशन बदल गई है (मुझे लगता है कि पर्ल 5.14 में) उदा। (?i-xsm:foo) से (?^i:foo), जो दर्द को पार्सिंग करता है।

मैं perl के संस्करण की जांच कर सकता हूं, या दोनों मामलों को संभालने के लिए केवल पार्सर लिख सकता हूं, लेकिन कुछ मुझे बताता है कि आत्मनिरीक्षण की एक बेहतर विधि उपलब्ध होनी चाहिए।

उत्तर

6

पर्ल में, आप re::regexp_pattern का उपयोग करेंगे।

my $re = qr/foo/i; 
my ($pat, $mods) = re::regexp_pattern($re); 
say $pat; # foo 
say $mods; # i 

आप regexp_pattern के स्रोत से देख सकते हैं, वहाँ है कि सूचना प्राप्त करने के लिए एपीआई में कोई समारोह है, तो मैं सुझाव है कि आप भी XS से बहुत कि फ़ंक्शन को कॉल करें।

perlcall कवर सी से पर्ल कार्यों बुला मैं निम्नलिखित अपरीक्षित कोड के साथ आया था:

/* Calls re::regexp_pattern to extract the pattern 
* and flags from a compiled regex. 
* 
* When re isn't a compiled regex, returns false, 
* and *pat_ptr and *flags_ptr are set to NULL. 
* 
* The caller must free() *pat_ptr and *flags_ptr. 
*/ 

static int regexp_pattern(char ** pat_ptr, char ** flags_ptr, SV * re) { 
    dSP; 
    int count; 
    ENTER; 
    SAVETMPS; 
    PUSHMARK(SP); 
    XPUSHs(re); 
    PUTBACK; 
    count = call_pv("re::regexp_pattern", G_ARRAY); 
    SPAGAIN; 

    if (count == 2) { 
     /* Pop last one first. */ 
     SV * flags_sv = POPs; 
     SV * pat_sv = POPs; 

     /* XXX Assumes no NUL in pattern */ 
     char * pat = SvPVutf8_nolen(pat_sv); 
     char * flags = SvPVutf8_nolen(flags_sv); 

     *pat_ptr = strdup(pat); 
     *flags_ptr = strdup(flags); 
    } else { 
     *pat_ptr = NULL; 
     *flags_ptr = NULL; 
    } 

    PUTBACK; 
    FREETMPS; 
    LEAVE; 

    return *pat_ptr != NULL; 
} 

उपयोग:

SV * re = ...; 

char * pat; 
char * flags; 
regexp_pattern(&pat, &flags, re); 
+0

मुझे लगता है कि इस तरह से है जाने के लिए, धन्यवाद – friedo

+0

@friedo, जोड़ा (untested) एक्सएस कोड। – ikegami

+0

धन्यवाद, @ikegami। मैं आपके सी कोड के साथ शुरुआती बिंदु के रूप में जो कुछ चाहता था उसे प्राप्त करने में सक्षम था। ध्यान देने योग्य बात यह है कि वापसी मूल्यों को रिवर्स ऑर्डर में पॉप किया जाना चाहिए (इसलिए 'flags_sv' दूसरे के बजाय पहले आता है।) – friedo

3
use Data::Dump::Streamer ':util'; 
my ($pattern, $flags) = regex(qr/foo/i); 
print "pattern: $pattern, flags: $flags\n"; 
# pattern: foo, flags: i 

लेकिन यदि आप हाल ही की सुविधाओं को सीमित करने की कोशिश कर रहे हैं, तो आपके पास सिर्फ/u की जांच करने के लिए बहुत अधिक काम है।