Home > Net >  Is there perl line to increment a number in a line in a file?
Is there perl line to increment a number in a line in a file?

Time:07-01

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.

CodePudding user response:

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.

CodePudding user response:

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? Then let's match, and change, that

perl -pe's{\-p\s /\S [^0-9]\K([0-9] )\b}{ 1 $1 }e' file

Prints as expected on the provided input. To change the file in-place add the -i, as in the question, after thorough testing.

This makes assumptions, since the quetion isn't very precise (for example, that a path has no spaces). It can be tweaked -- and perhaps simplified -- depending on the exact requirements. If the question is updated with more details I can update (or offer alternatives).


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 (twenty years old). Then \K may not work, and 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}{ $1.(1 $2) }e' file

A number can be expected to lose the leading zero(s), if there are any, with the above code (even thoughfor a string like in the question it keeps it). If that is a problem we can assign the $1 to a variable and increment that, when leading zeros are kept. A nice trick from jhnc in a comment keeps it compact, too

perl -pe's{(\-p\s /\S [^0-9])([0-9] )\b}{ $1.(  ($_=$2)) }e' file

Or, if that's too much trickery for someone's test just add a variable

perl -pe's{(\-p\s /\S [^0-9])([0-9] )\b}{ $n = $2; $1.(  $n) }e' file

(with strict in place that'd need to be my $n = $2)

  • Related