Wednesday, April 27, 2022

[SOLVED] Regex: why can't I use a capture group inside curly braces {}

Issue

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've 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?


Solution

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/./'


Answered By - choroba
Answer Checked By - Mary Flores (WPSolving Volunteer)