Home > Enterprise >  During Perl substitution, increase the output with spaces in order it is of the same length as the i
During Perl substitution, increase the output with spaces in order it is of the same length as the i

Time:07-05

(Disclaimer: I don't understand much of Perl!)

A (nice!) answer to this question of mine advised me to use (more or less) the following perl trick for a tricky substitution:

perl -pe 's#μ(. ?)>(. ?)(?:\&(. ?))?¢¢# sprintf(":%s:`%s`", $1, ($3 eq "" or $2 eq $3) ? $2 : "$3 <$2>")#ge'

And, indeed, that works nicely:

echo "μctanpkg>a4&a4¢¢" | perl -pe 's#μ(. ?)>(. ?)(?:\&(. ?))?¢¢# sprintf(":%s:`%s`", $1, ($3 eq "" or $2 eq $3) ? $2 : "$3 <$2>")#ge'

returns:

:ctanpkg:`a4`

Now, I need to add at the end of this substitution as many spaces as needed in order the output string is of the same length as the input one.

How could I achieve such a result?

CodePudding user response:

You can use a second sprintf to do that, with a pattern that uses left-justify. The length can be passed in as an argument. The pattern for that is as follows.

printf "<%-*s>", 6, "a";   # prints "<a     >"

You can get the length of the last successful match with $&, as documented in perlvar.

perl -pe 's#μ(. ?)>(. ?)(?:\&(. ?))?¢¢# sprintf("%-*s", length($&), sprintf(":%s:`%s`", $1, ($3 eq "" or $2 eq $3) ? $2 : "$3 <$2>"))#ge'

With your example input, this isn't visible as it's using spaces. But if we add extra <> to the pattern, you can see that it's working.

#                                                                           V     V
$ echo "μctanpkg>a4&a4¢¢" | perl -pe 's#μ(. ?)>(. ?)(?:\&(. ?))?¢¢# sprintf("<%-*s>", length($&), sprintf(":%s:`%s`", $1, ($3 eq "" or $2 eq $3) ? $2 : "$3 <$2>"))#ge'
<:ctanpkg:`a4`       >

This will also work for lines with multiple matches.

echo "μctanpkg>a4&a4¢¢ μctanpkg>a4&a4¢¢" | perl -pe 's#μ(. ?)>(. ?)(?:\&(. ?))?¢¢# sprintf("<%-*s>", length($&), sprintf(":%s:`%s`", $1, ($3 eq "" or $2 eq $3) ? $2 : "$3 <$2>"))#ge'
<:ctanpkg:`a4`      > <:ctanpkg:`a4`      >

Please note that $& used to incur a performance penalty in older Perls. This was fixed in 5.20. Even if you are on a version below that, your use-case probably isn't impacted very much.

  • Related