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