2017-03-13 5 views
10

मैं overload constants in regular expressions पर कोशिश कर रहा हूं।जब मैं एक स्ट्रिंग चर का उपयोग करता हूं तो मेरा ओवरलोड :: निरंतर उप ट्रिगर नहीं होता है?

$test = "foo bar Max Fast bar foo"; 
($test, $name) = ChopPattern($test, '\nom'); 
say $test; 
say $name; 
:

sub ChopPattern { 
    my $string= shift; 
    my $pattern = shift; 

    if($string =~ m/$pattern/) { 
     $string =~ s/$&/ /g; 
     return ($string, $&); 
    } else { 
     return ($string, ''); 
    } 
} 

यहाँ मेरी परीक्षा है:

package Tagger; 
use overload; 

sub import { overload::constant 'qr' => \&convert } 

sub convert { 
    my $re = shift; 
    $re =~ s/\\nom/((?:[A-Z]{1}[a-z]+\\s*){2,3}(\\((\\w|\\s)+\\)+?)*)/xg; 
    return $re; 
} 

1; 

यहाँ सबरूटीन जिसमें मैं अधिक भार आरंभ करवाना चाहते है: यहाँ मेरी टैगर पैकेज है


मैं परीक्षण पैटर्न, \nom, सबरूटीन के मैच में hardwire हैं:

sub ChopPattern { 
    my $string= shift; 
    my $pattern = shift; 

    if($string =~ m/\nom/) { 
     $string =~ s/$&/ /g; 
     return ($string, $&); 
    } else { 
     return ($string, ''); 
    } 
} 

परीक्षण सही जवाब पैदावार:

foo bar bar foo 
Max Fast 

लेकिन अगर मैं ऊपर के रूप में मैच में $pattern का उपयोग परीक्षण उपज:

foo bar Max Fast bar foo 
<null line> 

क्या कोई कारण है कि \nom टैगर ट्रिगर करता है लेकिन \nom के बराबर एक चर नहीं है?

यहाँ पर्ल के संस्करण का ब्यौरा इस्तेमाल किया जा रहा हैं:

This is perl 5, version 16, subversion 3 (v5.16.3) built for MSWin32-x64-multi-thread (with 1 registered patch, see perl -V for more detail) 

Copyright 1987-2012, Larry Wall 

Binary build 1604 [298023] provided by ActiveState http://www.ActiveState.com 
Built Apr 14 2014 15:29:45 
+0

कुछ अपवॉट्स के लायक, क्योंकि यह मेरे साथ कभी नहीं हुआ कि आप इस तरह के रेगेक्स इंजन को अधिभारित कर सकते हैं। – Sobrique

+2

@ सोब्रीक: यह संभव है, लेकिन यह करना बहुत अच्छी बात नहीं है। एक दूरी पर कार्रवाई और वह सब। – Borodin

+0

यह पहले भी यह नहीं देखा था। सबसे पहले मैंने सोचा कि वे क्या समझते हैं कि 'अधिभार' क्या करता है। लेकिन यह वास्तव में बहुत तार्किक है। मैं वास्तव में इसके लिए उपयोग-केस नहीं देखता हूं। यह अजीब है। – simbabque

उत्तर

4

प्रोग्रामिंग पर्ल का कहना है कि स्थिरांक पर overload::constant काम करता है।

जब भी पर्ल टोकनर निरंतर संख्या का सामना करता है तो आप जो भी हैंडलर पूर्णांक और फ्लोट के लिए प्रदान करते हैं, उन्हें बुलाया जाएगा।

जब आप m/$pattern/ पर कॉल करते हैं, तो यह स्थिर नहीं है। यह एक चर है।

($test, $name) = ChopPattern($test, '\nom'); 

अब '\nom' एक निरंतर है, लेकिन यह एक स्ट्रिंग है। इसे qr// में बदलें और आपके पास एक नियमित अभिव्यक्ति होगी जिसमें स्थिरता हो।

($test, my $name) = ChopPattern($test, qr'\nom'); 

ChopPattern में पैटर्न मैचों की एक ही रह सकते हैं:

if($string =~ m/$pattern/) { ... } 

क्योंकि वहाँ अब एक नियमित अभिव्यक्ति में एक निरंतर हिस्सा है, पर्ल अपने convert अधिभार कहते हैं, और अपने रेगुलर एक्सप्रेशन से कर सकते हैं।


चलिए इसे क्रिया में देखते हैं। याद रखें कि पर्ल संकलन समय पर इस ओवरलोडिंग प्रतिस्थापन कर रहा है, जब यह स्रोत कोड को पार करता है।

BEGIN { 
    overload::constant 'qr' => sub { 
     my $re = shift; 
     $re =~ s/\\nom/foobar/; 
     return $re; 
    }; 
} 

sub match { 
    my ($t, $p) = @_; 
    $t =~ m/$p/; 
} 
match('some text', '\nom'); 

यह महत्वपूर्ण क्या कोड नहीं है:

इस उदाहरण पर विचार। जब हम इसे deparse, हम इस उत्पादन प्राप्त करें:

$ perl -MO=Deparse scratch.pl 
sub BEGIN { 
    use warnings; 
    use strict; 
    use feature 'say'; 
    overload::constant('qr', sub { 
     my $re = shift(); 
     $re =~ s/\\nom/foobar/; 
     return $re; 
    } 
    ); 
} 
sub match { 
    use warnings; 
    use strict; 
    use feature 'say'; 
    BEGIN { 
     $^H{'qr'} = 'CODE(0x147a048)'; 
    } 
    my($t, $p) = @_; 
    $t =~ /$p/; 
} 
use warnings; 
use strict; 
use feature 'say'; 
BEGIN { 
    $^H{'qr'} = 'CODE(0x147a048)'; 
} 
match 'some text', '\\nom';      # <-- here 

हम देख सकते हैं कि हैंडलर स्थापित किया गया था, लेकिन समारोह कॉल में अंतिम पंक्ति में, वहाँ '\\nom' स्ट्रिंग है।

अब यदि हम स्ट्रिंग के बजाय उद्धृत अभिव्यक्ति qr// का उपयोग करते हैं, तो चीजें बदलती हैं।

BEGIN { 
    overload::constant 'qr' => sub { 
     my $re = shift; 
     $re =~ s/\\nom/foobar/; 
     return $re; 
    }; 
} 

sub match { 
    my ($t, $p) = @_; 
    $t =~ m/$p/; 
} 
match('some text', qr/\nom/); 

अब बहिष्कृत कार्यक्रम में अचानक foobar शामिल है। रेगेक्स बदल दिया गया था।

$ perl -MO=Deparse scratch2.pl 
sub BEGIN { 
    use warnings; 
    use strict; 
    use feature 'say'; 
    overload::constant('qr', sub { 
     my $re = shift(); 
     $re =~ s/\\nom/foobar/; 
     return $re; 
    } 
    ); 
} 
sub match { 
    use warnings; 
    use strict; 
    use feature 'say'; 
    BEGIN { 
     $^H{'qr'} = 'CODE(0x1e81048)'; 
    } 
    my($t, $p) = @_; 
    $t =~ /$p/; 
} 
use warnings; 
use strict; 
use feature 'say'; 
BEGIN { 
    $^H{'qr'} = 'CODE(0x1e81048)'; 
} 
match 'some text', qr/foobar/;      # <-- here 

यह कोड चलाने से पहले ऐसा हुआ था।

यदि हम संकलन समय के बाद दुभाषिया चलाने के लिए -MO=Concise दोनों प्रोग्राम चलाते हैं, तो हमें और प्रमाण मिलता है कि यह सामग्री केवल स्रोत कोड में वास्तविक स्थिरांक पर काम करती है, और गतिशील रूप से काम नहीं कर सकती है।

$ perl -MO=Concise scratch.pl 
8 <@> leave[1 ref] vKP/REFC ->(end) 
1  <0> enter ->2 
2  <;> nextstate(main 2529 scratch.pl:5950) v:%,R,*,&,{,x*,x&,x$,$,469762048 ->3 
7  <1> entersub[t1] vKS/TARG,2 ->8 
-  <1> ex-list K ->7 
3   <0> pushmark s ->4 
4   <$> const(PV "some text") sM ->5  # <-- here 
5   <$> const(PV "\\nom") sM ->6 
-   <1> ex-rv2cv sK/2 ->- 
6    <$> gv(*match) s ->7 

और qr// साथ:

$ perl -MO=Concise scratch2.pl 
8 <@> leave[1 ref] vKP/REFC ->(end) 
1  <0> enter ->2 
2  <;> nextstate(main 2529 scratch2.pl:5950) v:%,R,*,&,{,x*,x&,x$,$,469762048 ->3 
7  <1> entersub[t1] vKS/TARG,2 ->8 
-  <1> ex-list K ->7 
3   <0> pushmark s ->4 
4   <$> const(PV "some text") sM ->5  # <-- here 
5   </> qr(/"foobar"/) lM/RTIME ->6 
-   <1> ex-rv2cv sK/2 ->- 
6    <$> gv(*match) s ->7 
5

वहाँ एक कारण यह है कि \nom चलाता है टैगर लेकिन \nom करने के लिए एक चर बराबर नहीं है है?

क्योंकि '\nom' एक स्ट्रिंग शाब्दिक, नहीं एक regex के एक निरंतर टुकड़ा है:

$ perl -Moverload -E'BEGIN { overload::constant qr => sub { say "@_" } } $foo =~ "bar"' 
$ perl -Moverload -E'BEGIN { overload::constant qr => sub { say "@_" } } $foo =~ /bar/' 
bar bar qq 

तुम क्या कर रहे हैं एक बुरा विचार है। निम्नलिखित कार्यान्वयन ज्यादा समझने के लिए आसान है और regex अर्थ विज्ञान हर जगह परिवर्तन नहीं करता है:

use strict; 
use warnings 'all'; 
use 5.010; 

sub chop_pattern { 
    my ($string, $pattern) = @_; 

    my %mapping = (
     '\nom' => qr/((?:[A-Z][a-z]+\s*){2,3}(?:\([\w\s]+\)+?)*)/ 
    ); 

    if (exists $mapping{$pattern}) { 
     my $matched = $string =~ s/$mapping{$pattern}/ /g; 
     return $string, $1 if $matched; 
    } 

    return $string, ''; 
} 

my ($string, $chopped) = chop_pattern('foo Bar Baz qux', '\nom'); 
say "<$string> <$chopped>"; 

आउटपुट:

<foo qux> <Bar Baz > 

मैं क्योंकि आप हैंडल करना चाहते हैं अनुमान लगा रहा हूँ आप अधिभार के साथ चला गया एक से अधिक " जादू "स्ट्रिंग (उदाहरण के लिए \nom)। मैंने ऐसा किया है जो एक सरल हैश के साथ है जो तारों को फिर से जोड़ता है।

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

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