How to insert a number after a group match in a find-replace regex? Like this:
mat367 -> mat0363
fis434 -> fis0434
chm185 -> chm0185
I was renaming those files with the rename
command line tool. I tried the following regex
rename 's/([a-z]{3})(.+)/$1\0$2/g' *
s
at the beginning means replace*
at the end means every file.([a-z]{3})(.+)
is the regex to match the name of the files.$1\0$2
is the replacement.I thought the regex above would insert a 0 after the first group match ($1), but it doesn't insert anything. So I tried:
rename 's/([a-z]{3})(.+)/$10$2/g' *
However, this makes the regex think that I'm refering to $10 (group number teen), and throws errors.
I'd like to know if it is possible to accomplish my goal in a single regex. In other words, don't use the rename command twice or more. For example, use the rename command to insert a letter instead of 0, and then replace that letter with 0, but this would require two regex, two commands. Using only one regex may be useful in contexts other than renaming files.
Note: It seems like the regex used by rename
is based on perl
. That may help if someone knows perl
.
The argument is evaluated as Perl code, and you are correct about Perl seeing $10
.
In a double-quoted string literal (which the replacement expression is), you can only safely escape non-word characters. Like letters, digits are word characters. Specifically, \0
refers to the NUL character. So using \0
is not acceptable.
The solution is to use curlies to delimit the var name.
rename 's/([a-z]{3})(.+)/${1}0$2/g' *
Another way to address the problem in this case is by side-stepping it. Since there's no need to replace the text before the insertion point, we don't need to capture it.
rename 's/[a-z]{3}\K(.+)/0$1/g' *
We can further simplify the second solution.
The .+
ensures there's going to be at most one match per line, so the above can be simplified to the following (assuming none of the file names contain a line feed):
rename 's/[a-z]{3}\K(.)/0$1/' *
We could even avoid the remaining capture with a look-ahead.
rename 's/[a-z]{3}\K(?=.)/0/' *
But is there really a reason to look-ahead? The following isn't equivalent as it doesn't require anything to follow the letters, but I don't think that's a problem.
rename 's/[a-z]{3}\K/0/' *
Finally, if the goal is to add a zero before the number (and thus before the first digit encountered), I'd use
rename 's/(?=\d)/0/' *