Reputation: 29
I have a file with one line like:
onspaces -a dataidx -p /dev/itest17/idx_dataidx20 -o 0 -s 2097150
I need to increment the number by one so the output would be:
onspaces -a dataidx -p /dev/itest17/idx_dataidx21 -o 0 -s 2097150
The could also have a line such as:
onspaces -a dataidx -p /dev/itest17/foobar01 -o 0 -s 2097150
which would result in
onspaces -a dataidx -p /dev/itest17/foobar02 -o 0 -s 2097150
I have tried
`perl -i -pe 'if ($. == 1)
{($n) = ($m) = /([09]+)$/;
++$m;s/$n/$m/g;
} else {s/$n(?= )/$m/;}' in_file`
which was a solution to a previous question that I asked that was solved, but this one seems to be a bit different. Thanks in advance!
Note: I'm using an ancient version of Perl, 5.8.3.
Upvotes: 0
Views: 194
Reputation: 66881
The only really "moving part" here is about finding the place in the line where that number is. It appears that it is the end of a path following -p
perl -pe's{\-p\s+/\S+[^0-9]\K([0-9]+)\b}{ $n = $1; ++$n }e' file
Prints as expected on the provided input. The "maneuver" with $n
(instead of just 1+$1
) is there to ensure that the leading zero(s) stay.† To change the file in-place add -i
, as in the question, after thorough testing.
This makes assumptions, since the quetion isn't very precise (for example, that paths have no spaces). It can be tweaked, and perhaps simplified, depending on requirements' details.
A brief explanation and alternatives
The /e
modifier makes the replacement side be evaluated as code so we can do our math there, and what that code returns is then used as the replacement. The \K
nicely "drops" everything matched up to that point, so the replcement won't touch previous matches.
However, comments clarify that this is perl v5.8.3; \K
wasn't there back then (twenty years ago). Without it we have to capture everything preceding the number to change, and put it back
perl -pe's{(\-p\s+/\S+[^0-9])([0-9]+)\b}{ $n=$2; $1.(++$n) }e' file
Finally, the [^0-9]
(not a digit) is there to "stop" the previous greediness of \S+
, needed to match a path, so that the last number in the path can be matched in full (\S+
would only leave one digit for the final [0-9]+
).
† When a number is used in numeric context it can be expected to lose the leading zero(s) (ie, it normally does). However, with the auto-increment operator it doesn't if it is used as a string, and in the replacement side of a regex it is.
A trick from jhnc
in a comment keeps it compact, too
perl -pe's{(\-p\s+/\S+[^0-9])\K([0-9]+)\b}{ ++($_=$1) }e' file
or, in the perl-5.8.3-has-no-\K
case
perl -pe's{(\-p\s+/\S+[^0-9])([0-9]+)\b}{ $1.(++($_=$2)) }e' file
Upvotes: 2
Reputation: 241918
Similarly to the solution I provided to you previously:
perl -i~ -pe 's/([0-9]+)(?= -o)/$x = $1; ++$x/e' file
I.e. find a sequence of digits [0-9]+
followed by a space and -o (?= -o)
, replace the digits by the incremented number. The /e
interprets the replacement as a code to run, using ++
ensures the leading zeroes are kept.
Upvotes: 3