in reply to Combining regexes

I didn't think the OPed code was really so terrible to begin with (once the  $plsname =~ s/\//_/g; statement is fixed). But in an attempt to "one-liner-ize" the code, and building on BrowserUk's post (and using my preferred regex practices), here's this:

c:\@Work\Perl\monks>perl -wMstrict -le "my $curdir = 'Y:\Music\Schubert\Lieder\Terfel'; my $startdir = 'Y:\mUsIc'; ;; my $plsname = $curdir; $plsname =~ s{ \A (?i) \Q$startdir\E \\ (.+) \z } { (my $r = $1) =~ tr{\\}{_}; $r . '.pls'; }xmse; print qq{'$plsname'}; " 'Schubert_Lieder_Terfel.pls'
And is that really any better? Again, your call.

If you have Perl version 5.14+, it's possible to slightly simplify the  s/// replacement executable code above to
    $1 =~ tr{\\}{_}r . '.pls';
and in fact you could go all the way to

c:\@Work\Perl\monks>perl -wMstrict -le "my $curdir = 'Y:\Music\Schubert\Lieder\Terfel'; my $startdir = 'Y:\mUsIc'; ;; my $plsname = $curdir =~ s{ \A (?i) \Q$startdir\E \\? }{}xmsr =~ tr{\\}{_}r . '.p +ls'; print qq{'$plsname'}; " 'Schubert_Lieder_Terfel.pls'
I hope this hasn't gone too "all PerlMonks" on you, and includes at least a hint (update: but not a single drop!) of Socrates.

Update: For info on the  /r modifier added in Perl version 5.14, see  s/// in Regexp Quote-Like Operators and  tr/// in Quote-Like Operators, both in perlop.


Give a man a fish:  <%-{-{-{-<

Replies are listed 'Best First'.
Re^2: Combining regexes
by davies (Monsignor) on May 21, 2016 at 19:06 UTC

    Much reading later - and thank you for all the references in your other post, only some of which I had read previously - I think I understand what you are doing. I do have some questions, though. Am I right in thinking that the (?i) has the same effect as an i qualifier with xmsr? If not, what is the difference (and where is it documented, please)? If so, and I appreciate that you have stated "my own preferred practices" which exempts you from needing a reason, is there a reason why you prefer to have the qualifiers separately?

    How come none of the spaces in { \A (?i) \Q$startdir\E \\? } are treated as matchable characters? I suspect it's one of your qualifiers, but I couldn't find it explained in any of the docs I read, unless it's part of x, and I haven't looked for the documentation for that beyond reading that it means "extended regexes".

    I find your final assignment ($var = $var =~ regex =~ regex) rather confusing, as it seems to need to work from left to right at some times and from right to left at others. I know things joining things like map, grep & sort result in the expression working right to left. I don't remember seeing three assignment-like = signs in a Perl statement before, which may be part of my confusion. Is the order irrelevant, and if not, what are the rules for the direction of evaluation?

    Thanks and regards,

    John Davies

      Am I right in thinking that the (?i) has the same effect as an i qualifier with xmsr?

      Yes — almost. In, e.g.,  s{ ... }{...}xmsi the  /i modifier affects the regex match globally. A  (?i) extended pattern only has effect from the point of its appearance in the regex to the end of the regex pattern scope — which may or may not be the end of the regex! (See Extended Patterns. I must apologize: I did not mention that extended patterns are only available from Perl version 5.10 onward; I assume you have this.) I prefer the embedded  (?i) form because it is more visible and because it gives more control: case sensitivity can be turned on and off at will in a regex, and its scope closely controlled. In general, "my own preferred practices" are that the  qr// operator has only the  /xms modifiers applied to the operator, and all other modifiers , e.g., (?i), scoped within the operator. This practice just generalizes to the  m//xms and  s///xms operators. The latter two operators can also take  /g /e /r modifiers which can only be applied to the operator as a whole.

      ... none of the spaces in { ... } are treated as matchable characters? I suspect it's ... x ...

      Yes, exactly. Allowing whitespace not to be part of the pattern eases the strain on these old eyes, a great blessing after so many years toiling in the scriptorium. See  /x in Modifiers.

      I find your final assignment ($var = $var =~ regex =~ regex) rather confusing, as it seems to need to work from left to right at some times and from right to left at others.

      It might have been helpful if I had thrown in a few disambiguating parentheses. But you can always add your own with O and B::Deparse:
      (Here I wanted to give an example of the deparsed code, but for some reason I don't understand, it didn't work out! Quickly moving on...)
      Anyway, by hand:

      c:\@Work\Perl\monks>perl -wMstrict -le "my $curdir = 'Y:\Music\Schubert\Lieder\Terfel'; my $startdir = 'Y:\mUsIc'; ;; my $plsname = ((($curdir =~ s{ \A (?i) \Q$startdir\E \\? }{}xmsr) =~ tr{\\}{_}r) +. '.pls'); print qq{'$plsname'}; " 'Schubert_Lieder_Terfel.pls'
      Working in order of precedence (more or less inside-out in this case):
      1. ($curdir =~ s{ \A (?i) \Q$startdir\E \\? }{}xmsr)
        A substitution is done on  $curdir and the substituted string returned courtesy of the  /r modifier of 5.14+;
      2. (($curdir =~ s{ ... }{}xmsr) =~ tr{\\}{_}r)
        The string returned by the  s///r substitution is operated upon by  tr///r and the translated string is returned;
      3. ((($curdir =~ s{ ... }{}xmsr) =~ tr{\\}{_}r) . '.pls')
        The string  '.pls' is appended to the string returned by  tr///r and;
      4. The whole thing is finally assigned to $plsname. Whew!

      Is the order irrelevant, and if not, what are the rules for the direction of evaluation?

      The order is very relevant, and is discussed in Operator Precedence and Associativity in perlop: see the  =~ (binding) and  . (concatenation) and  = (assignment) operators.

      Update: Layout of  <ol> above changed – improved?


      Give a man a fish:  <%-{-{-{-<