Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

Re: RegExp: pos management in global substitution

by AnomalousMonk (Canon)
on Sep 03, 2011 at 15:03 UTC ( #923998=note: print w/replies, xml ) Need Help??

in reply to RegExp: pos management in global substitution

I agree that a two-step approach (i.e., match for name_a, then delete unwanted params) is best. However, here's an 'advanced' (read: unnecessarily complex) way that doesn't use the  /e modifier:

>perl -wMstrict -le "my @txt = ( '{name_b param_v=\"wh\"}', '{name_a param_x=\"abc\" param_a=\"fsd\" param_y=\"def\"}', '{name_z param_sd=\"zka\" param_s=\"df\"}', '{name_a param_y=\"wtf\" param_z=\"kro\" param_c=\"ptz\" param_ch=\ +"www\"}', '{name_a param_sd=\"zka\" param_y=\"wtf\"}', ); ;; my $not_p_xy = qr{ (?! param_ [xy] \b) }xms; my $not_sp_param = qr{ (?! \s+ $not_p_xy param_ \w+) . }xms; ;; for my $s (@txt) { print qq{'$s'}; $s =~ s( (?: \G (?<! \A) | \A {name_a) $not_sp_param* \K \s+ $not_p_xy \w+ = \" [^^\"]* \" ) ()xmsg; print qq{'$s' \n}; } " '{name_b param_v="wh"}' '{name_b param_v="wh"}' '{name_a param_x="abc" param_a="fsd" param_y="def"}' '{name_a param_x="abc" param_y="def"}' '{name_z param_sd="zka" param_s="df"}' '{name_z param_sd="zka" param_s="df"}' '{name_a param_y="wtf" param_z="kro" param_c="ptz" param_ch="www"}' '{name_a param_y="wtf"}' '{name_a param_sd="zka" param_y="wtf"}' '{name_a param_y="wtf"}'


  1. Removed extraneous  (?: ) grouping around  \K expression above. Example output unchanged.
  2. I agree with Re^2: RegExp: pos management in global substitution regarding efficiency, and have further simplified (IMO) to:
    sub xform { my ($string, ) = @_; my $xy = qr{ [xy] }xmso; my $val = qr{ = ' [^']* ' }xmso; my $param_ = qr{ \s+ param_ }xmso; my $param_xy = qr{ $param_ $xy $val }xmso; my $param_any = qr{ $param_ \w+ $val }xmso; $string =~ s{ (?: \G (?<! ^) | ^ \{ name_a) $param_xy*+ \K $param_any } ''xmsg; return $string; }
    Update: Note that I'm using ' (single-quote) instead of " (double-quote) as the parameter value delimiter in my code and testing. This uses 5.10+ regex features. This has withstood everything I have thrown at it (including the multi-line example of the OP!), and I think it's my final answer. (This even qualifies as perhaps not unnecessarily complex!)

Replies are listed 'Best First'.
Re^2: RegExp: pos management in global substitution
by OlegG (Monk) on Sep 03, 2011 at 17:55 UTC
    Interesting, but it depends of new line. In my example each tag separated by new line, but it is special case.
    And it seems your regexp could be more efficient:
    s( (?: (?: \G (?<! \A) | \A {name_a) $not_sp_param*+ \K) \s+ \w+ = \" [^^\"]* \" ) ()xmsg;
        Your variant still depends of new line. I mean it doesn't work properly with
        {name_b param_v="wh"}{name_a param_x="abc" param_a="fsd" param_y="def" +} {name_z param_sd="zka" param_s="df"}{name_a param_y="wtf" param_z="kro +" param_ch="www"}
        But thanks anyway. When I parsed your regexp I found new for me \K and totally understood how \G works. See below my solution based on your. Seems it works properly.
        s/ (?:\{name_a | \G) [^{}]+? \K \w++(?<!param_[xy]) ="[^"]+" //xg;

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://923998]
[Corion]: ambrus: Yeah, I read that, but it's somewhat vague as in what I really have to implement, and where/how my "other" mainloop should/needs to call AnyEvent
[Corion]: (or maybe I just work better from existing code that I munge until it works and I understand it rather than a short abstract text like "implement everything that's needed" ;) )
[ambrus]: Corion: I think in this case you can get away with only a stub for idle, one that always dies when you create it, because AnyEvent::HTTP doesn't use it, not even indirectly through AnyEvent::Handle or AnyEvent::Socket or AnyEvent::DNS.
[Corion]: The "and I understand it" part is optional.
[Corion]: ambrus: Yes but I also need to implement the file / IO watcher, because Prima has that (in Prima::File), and I need to supply the appropriate thing to make push_write etc. work with Prima
[ambrus]: Corion: yes, you need to implement the io watcher, which should be simple because Prima::File is basically that, and the timer watcher form Prima::Timer
[Corion]: ... or so I think. As I said, I'm somewhat vague on how to make AnyEvent cooperate with a callback-driven IO event loop that gives me callbacks when data is available or can be written
[ambrus]: what push_write thing? I don't think you need that. that's implemented generically by AnyEvent::Handle

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (9)
As of 2016-12-08 12:15 GMT
Find Nodes?
    Voting Booth?
    On a regular basis, I'm most likely to spy upon:

    Results (141 votes). Check out past polls.