Home > Software design >  Regex: why can't I use a capture group inside curly braces {}
Regex: why can't I use a capture group inside curly braces {}

Time:04-22

I want to replace the nth charater of a line to '.', with n being line dependent and can be provided on the line itself, e.g. a example file can look like this:

$cat test
0 ABCD
1 ABCD
2 ABCD

The desired output is

0 .BCD
1 A.CD
2 AB.D
3 ABC.

I'm tried capturing the number and using \1 inside {}, but it doesn't work:

$ cat test | perl -pe 's/([0-9]) ([A-Z]{\1})./\1 \2./'
0 ABCD
1 ABCD
2 ABCD

whereas using a normal number inside {} gives the desired output:

$ cat test | perl -pe 's/([0-9]) ([A-Z]{2})./\1 \2./'
0 AB.D
1 AB.D
2 AB.D

Using perl (and not sed) because I know that using capturing groups in the pattern does in principle work:

$ echo 'KALLO' | perl -pe 's/([A-Z])\1/__/'
KA__O

So my questions: Why doesn't my approach with {\1} work? How can I achieve what I want without using a loop?

CodePudding user response:

Perl expects a number after {, not a backslash.

You can build the pattern from variables, though, and use it in a substitution:

perl -pe '/^([0-9] )/; $p = "(.* .{$1})."; s/$p/$1./'

Or even, on Perl 5.010

perl -pe '/^([0-9] )/; $p = ".* .{$1}\\K."; s/$p/./'

CodePudding user response:

\1 means "match what the first capture captured". It makes no sense where you used it.

(??{ }) could be used.

$ perl -ple's/^(\d)  \s   (??{ "." x $1 }) \K . /./sxa' test
0 .BCD
1 A.CD
2 AB.D

How I'd do it:

$ perl -ple'
   my @F = split " ", $_, 2;
   substr( $F[1], $F[0], 1 ) = ".";
   $_ = join " ", @F;
' test
0 .BCD
1 A.CD
2 AB.D
  • Related