-1

I am looking for a perl/awk/sed command to auto-increment the number in column 7 Example line in file knownfile.txt:

The file has formatting and 7 columns.

today is a great day and it
is also an amazing day tomorrow now
blahblah foo today build number is 5928

I want to retain all formatting and simply replace 5928 with 5929 and save file

I tried:

awk '/blahblah/{ $7++; print $0 }' filename > tmp && mv tmp filename

It increments the number and I think it retains the formatting, but it only prints the edited line to the file.

Miller
  • 34,962
  • 4
  • 39
  • 60
user3642747
  • 47
  • 1
  • 3
  • 2
    Post more lines of sample input and expected output and format both. – Ed Morton May 15 '14 at 22:18
  • Is the number always in the same place, i.e. at the end of the line? – Tom Fenech May 15 '14 at 22:22
  • Tom, yes the number I want to replace is always at the end of the line. – user3642747 May 15 '14 at 22:26
  • FYI any operation you perform on a field (e.g. $7 above) WILL change the formatting because changing a field tells awk to recompile the record ($0) using the OFS value (a single space by default) between fields, so by default all chains of contiguous white space will be replaced by a single blank char. To avoid that, you need to operate on the record as a whole, not any 1 field in the record. – Ed Morton May 16 '14 at 12:52

5 Answers5

8
$ cat file
today is a great day and it
is also an amazing day tomorrow now
blahblah    foo   today     build number is     5928

$ awk '{sub(/[[:digit:]]+$/,$NF+1)}1' file
today is a great day and it
is also an amazing day tomorrow now
blahblah    foo   today     build number is     5929

If that doesn't do what you want then seriously THINK about what sample input and expected output you're posting as that's all we have to go on.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • 1
    Nice way of dealing with the formatting issue that mine suffers from (or _would_ suffer from if the input was different). I guess that there should be `/foo/` before the block though. – Tom Fenech May 16 '14 at 12:42
  • idk, I see some answers matching on /foo/ but I don't see any mention of that in the question. – Ed Morton May 16 '14 at 12:47
  • 1
    Good point, that seems to no longer be part of the question. Guess I need to keep up! +1 then for preserving the line format and fulfilling the brief. – Tom Fenech May 16 '14 at 12:49
6

Using a perl one-liner

perl -i -pe 's/(\d+)$/1+$1/e' knownfile.txt
Miller
  • 34,962
  • 4
  • 39
  • 60
1

Given that the number is always at the end of the line, you could do this in awk:

awk '/foo/{++$NF}1' file

where file is the file you want to operate on. This simply increments the value of the last column when the line contains the word "foo". The 1 at the end means perform the default action, which is to print the line.

To do this "in-place" on a file, you have to jump through a few hoops:

awk '/foo/{++$NF}1' file > tmp && mv tmp file

Newer versions of gawk support in-place editing but this will work everywhere.

Tom Fenech
  • 72,334
  • 12
  • 107
  • 141
  • like most languages, awk has a `++` operator so you can write `$NF++` or `++$NF` instead of `$NF = $NF+1`. – Ed Morton May 15 '14 at 22:47
  • 1
    @Ed in the interests of efficiency I'll use the pre-increment version ;) Thanks for pointing that out. I should've done that in the first place. – Tom Fenech May 15 '14 at 22:54
  • Actually, apparently when it saves the data it removes some of the formatting and that is causing an issue. Any way to keep the spacing / formatting of the line edited? – user3642747 May 15 '14 at 23:04
  • 1
    @user3642747 It works for the example in your question. If your file is different you should edit the question to make it clearer. – Tom Fenech May 15 '14 at 23:29
  • @user3642747 I have tried my command against your latest example and it works fine. What is the problem that you are experiencing? – Tom Fenech May 16 '14 at 00:38
  • 1
    @user3642747 When you increment a field like this, it will change the format to use the default Field Separator (one space) for whole the line. Look at Eds solution using `sub` to change the field without changing the format of the line. – Jotne May 16 '14 at 05:48
  • Good point @Jotne. Of course, this side-effect isn't apparent due to the fact that the question contains word that are only separated by one space... – Tom Fenech May 16 '14 at 06:37
0
$ perl -i -pe 's/\d+$/$&+($&>0)/e if /foo/' knownfile.txt

Doesn't see -32 as negative.

bobbogo
  • 14,989
  • 3
  • 48
  • 57
-1

This script has no downsides.

use Fcntl;
my $fh;
open $fh,"+<$ARGV[0]";
while(<$fh>) {
    if (/foo/) {
        s/(-?\d+)/(($1 > 0) ? ($1+1) : $1)/ge;
    }
    $file .= $_;
}
seek($fh, 0, SEEK_SET);
print $fh $file;
close $fh;
Astrinus
  • 412
  • 9
  • 19