13

I have one file with the date like below,let say file name is file1.txt:

2013-12-29,1

Here I have to increment the number by 1, so it should be 1+1=2 like..

2013-12-29,2 

I tried to use 'sed' to replace and must be with variables only.

oldnum=`cut -d ',' -f2 file1.txt`  
newnum=`expr $oldnum + 1`
sed -i 's\$oldnum\$newnum\g' file1.txt  

But I get an error from sed syntax, is there any way for this. Thanks in advance.

Soma
  • 861
  • 2
  • 17
  • 32
Naveen Reddy CH
  • 799
  • 2
  • 13
  • 23

6 Answers6

21

Sed needs forward slashes, not back slashes. There are multiple interesting issues with your use of '\'s actually, but the quick fix should be (use double quotes too, as you see below):

oldnum=`cut -d ',' -f2 file1.txt`  
newnum=`expr $oldnum + 1`
sed -i "s/$oldnum\$/$newnum/g" file1.txt 

However, I question whether sed is really the right tool for the job in this case. A more complete single tool ranging from awk to perl to python might work better in the long run.

Note that I used a $ end-of-line match to ensure you didn't replace 2012 with 2022, which I don't think you wanted.

Wes Hardaker
  • 21,735
  • 2
  • 38
  • 69
  • Thanks for your quick reply..:) I don't need awk here, as this is a small change. It is working well. – Naveen Reddy CH Dec 30 '13 at 09:57
  • No problem; don't forget to pick your favorite reply and accept it by clicking the checkbox. – Wes Hardaker Dec 30 '13 at 14:05
  • 1
    Sed does not need forward slashes, it needs a consistent separator. Backslashes just need escaping (doubling) in order to actually reach sed. – OJFord Oct 03 '20 at 12:27
7

usually I would like to use awk to do jobs like this following is the code might work

awk -F',' '{printf("%s\t%d\n",$1,$2+1)}' file1.txt
Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
michaeltang
  • 2,850
  • 15
  • 18
3

Here is how to do it with awk

awk -F, '{$2=$2+1}1' OFS=, file1.txt
2013-12-29,2

or more simply (this will file if value is -1)

awk -F, '$2=$2+1' OFS=, file1.txt

To make a change to the change to the file, save it somewhere else (tmp in the example below) and then move it back to the original name:

awk -F, '{$2=$2+1}1' OFS=, file1.txt >tmp && mv tmp file1.txt

Or using GNU awk, you can do this to skip temp file:

awk -i include -F, '{$2=$2+1}1' OFS=, file1.txt
Jotne
  • 40,548
  • 12
  • 51
  • 55
  • @Jotne - fails on `...,-1`; better to keep the braces, and probably also to make output explicit: `awk -F, '{$2=$2+1;print}' OFS=, ...` – Henk Langeveld Dec 30 '13 at 12:26
  • 1
    @HenkLangeveld Braces should be used yes, since `0` result would not be printed. But as far as I know `{$2=$2+1;print}` would give the same as `{$2=$2+1}1'`. – Jotne Dec 30 '13 at 13:43
  • @Jotne - correct, but the lone `1` me be overlooked (as a typo) to the uninitiated. Better to add a note explaining it in the answer. – Henk Langeveld Dec 30 '13 at 14:14
  • This worked for me, although I had to add a double & between the commands. awk -F, '{printf("%d\n",$1+1)}' nb.txt > nb2.txt && mv nb2.txt nb.txt (note that the file just has a number) – Nico Aug 11 '18 at 15:41
  • it has to be `&&` and not `&` otherwise awk is in background and mv could be done when the file is not done. – phschoen Mar 16 '22 at 09:15
  • @phschoen You are correct, fixed. Thanks In `Gnu awk` you can do `awk -i include -F, '{$2=$2+1}1' OFS=, file1.txt` to write without temp file. – Jotne Mar 16 '22 at 10:41
2

Another one-liner would be:

$ expr `cat /tmp/file 2>/dev/null` + 1 >/tmp/file

this works if the file doesn't exist or if the file doesn't contain a valid number - in both cases the file is (re)created with a value of 1.

Jeff Schaller
  • 2,352
  • 5
  • 23
  • 38
ScottG
  • 21
  • 1
1

Bash one liner option with BC. Sample:

$ echo 3 > test
$ echo 1 + $(<test) | bc > test
$ cat test
4

Also works:

bc <<< "1 + $(<test)" > test
BoeroBoy
  • 1,094
  • 11
  • 17
  • I like the solution, but it doesn't seem to work because of a read-and-write at the same time conflict. i.e. "test" ends up empty. – dhr_p Jun 19 '23 at 13:43
  • What shell or bash version are you on? Works for me in v5.2.15. – BoeroBoy Jul 10 '23 at 19:00
0

awk is the best for your problem, but you can also do the calculation in shell

In case you have more than one rows, I am using loop here

#!/bin/bash
IFS=,
while read DATE NUM
do
echo $DATE,$((NUM+1))
done < file1.txt
ray
  • 4,109
  • 1
  • 17
  • 12