1

I'm playing around with the \K construct during a substitution operation, but it appears that capture groups aren't available to the right side.

Code:

my $string = 'lowerupper';
$string =~ s/lower\K(\w+)/\U$1/;
print $string;

Output:

lowerupper

Expected Output:

lowerUPPER

Why is this / is it possible to achieve the above without capturing 'lower'.

Thanks,

Chris

Chris
  • 729
  • 6
  • 12
  • 2
    There is no reason this doesn't work, `\K` does not change the behaviour of anything. Works well for me. Check your code. – Casimir et Hippolyte Jul 07 '14 at 12:24
  • 1
    Thank you for bringing this to my attention. I am testing using codepad.org running Perl version 5.008 (`print $];`). I assume \K hadn't been introduced. – Chris Jul 07 '14 at 12:28
  • 3
    Indeed, the `\K` has been introduced since the 5.10 version. Thus the reason you didn't obtain the result is that your pattern didn't match the string. – Casimir et Hippolyte Jul 07 '14 at 12:29
  • 1
    An other possibility to not capture "lower" is to use a lookbehind: `(?<=lower)(\w+)` – Casimir et Hippolyte Jul 07 '14 at 12:32
  • @Casimir et Hippolyte, thanks for the alternative. Worth noting though that my actual regexp uses a variable length string before \K. – Chris Jul 07 '14 at 12:44
  • Why do you want to avoid capturing `lower`? You have the performance penalty of having captures with or without capturing `lower`. – ikegami Jul 07 '14 at 13:30
  • @ikegami, I wasn't aware that there would inherently be a performance penalty. I'm just experimenting with \K, I won't necessarily use as above. – Chris Jul 07 '14 at 13:46
  • 2
    @Chris, That's why `$&` is discouraged: It forces every match in the interpreter to suffer the penalty of captures, even if it does no capturing. – ikegami Jul 07 '14 at 13:53

1 Answers1

2

The change isn't occurring because the pattern doesn't match because you are using a version of Perl that predates the addition of \K. Always use use strict; use warnings;!

With 5.8,

$ perl -wle'
   my $string = "lowerupper";
   $string =~ s/lower\K(\w+)/\U$1/;
   print $string;
'
Unrecognized escape \K passed through at -e line 3.
lowerupper

With 5.10+,

$ perl -wle'
   my $string = "lowerupper";
   $string =~ s/lower\K(\w+)/\U$1/;
   print $string;
'
lowerUPPER

You can obtain the result you want using

s/(lower)(\w+)/$1\U$2/;

and

s/(?<=lower)(\w+)/\U$1/;

The first is probably a little more efficient.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • Thank you very much for your detailed response. I had a script composed of lots of different snippets I had been experimenting with, laziness => bad practices throughout i.e. not declaring vars => turn off strict / warnings! – Chris Jul 07 '14 at 13:54
  • Not using `use strict; use warnings;` just silences the errors messages; it doesn't make the errors go away. – ikegami Jul 07 '14 at 14:01
  • Understood. I wouldn't possibly write serious code without including those! – Chris Jul 07 '14 at 14:06
  • As for throwaway snippets, the first thing you should do when you can't explain an error is to stop silencing the errors. – ikegami Jul 07 '14 at 14:09
  • I will definitely from now on. Just to dispute your logic though, if the error is silent then I have nothing to explain ;). – Chris Jul 07 '14 at 14:25
  • You came here, so that's not true. – ikegami Jul 07 '14 at 14:42
  • I assumed there was no error, I wanted to understand why it "wasn't possible" / wanted an alternative solution. I totally understand what you inferred though, an error doesn't have to be in the form of a message. – Chris Jul 07 '14 at 14:55
  • @Chris, Then you appear to have a different definition of error than I do. I consider not getting the expected outcome to be on error. – ikegami Jul 08 '14 at 04:52
  • I agree. My point hasn't come across well. – Chris Jul 08 '14 at 15:54