Reputation: 61
I have a text file with 4 columns delimited by comma. As I am reading each record in a loop, I want to add a value to the 5th column depending on a condition. So if I know the row number and column number, how can I use awk/sed commands to replace/set value at that particular field without using temporary files? I want to update the file (directly) that I am reading from
inp.txt
a,b,c,d
e,f,g,h
i,j,k,l
Thanks, -sri
Upvotes: 0
Views: 24838
Reputation: 212218
You cannot directly edit the file with either awk
or sed
. Some versions of sed
have an option (-i
) that works with a temporary file and overwrites the original file, but it does not actually edit the file in place. This is not a big deal. Just do:
$ awk 'NR==5{ $(NF+1) = "new value"}1' OFS=, FS=, input-file > tmp.$$
$ mv tmp.$$ input-file
To add a new column to row 5 of input-file
. If you wish, you can use ed
to edit the file, but it makes more sense to use a temporary file. If you want to pretend that you aren't using a temporary file, and your sed supports -i
, you can do the same thing with:
sed -i '5s/$/,new value/' input-file
Even though most utilitites do not allow in-place modification of the file, it is simple to use one of the following sh
functions to emulate that behavior using temporary files:
edit() { local f=$1; shift; "$@" < $f > $f.$$ && mv $f.$$ $f; } # Break hard links
edit() { local f=$1; shift; "$@" < $f > $f.$$ && cat $f.$$ > $f && rm $f.$$; }
With either of these, you could use awk
to give the appearance of editing files in-place using edit filename awk awk-cmds
. The first version breaks hard links, but uses slightly less IO.
Upvotes: 2
Reputation: 67211
perl -i -F, -lane 'if($.==<row number>){$F[<column_number>-1]+=<add your stuff here>}print join(",",@F)' your_file
tested below:
>cat temp
b,c,d,g
r,g,d,s
execute for changing the 3rd column in second row:
>perl -i -F, -lane 'if($.==2){$F[2]=10}print join(",",@F)' temp
> cat temp
b,c,d,g
r,g,10,s
Upvotes: 1
Reputation: 915
You mean like this? this is the version don't using any temporary files.
[a@b ~]$ cat tmp | sed 's_^\(.*\),\(.*\),\(.*\),\(.*\)_\1,\2,\3,\4_g'
inp.txt
a,b,c,d
e,f,g,h
i,j,k,l
[a@b ~]$ cat tmp | sed 's_^\(.*\),\(.*\),\(.*\),\(.*\)_\1,sth,\3,\4_g'
inp.txt
a,sth,c,d
e,sth,g,h
i,sth,k,l
[a@b ~]$ sed -ie 's_^\(.*\),\(.*\),\(.*\),\(.*\)_\1,sth,\3,\4_g' tmp
[a@b ~]$ cat tmp
inp.txt
a,sth,c,d
e,sth,g,h
i,sth,k,l
Cheers,
Upvotes: 0
Reputation: 172
I can't speak for sed, but the purpose of awk isn't to edit files in place but to write to stdout.
But anyway, here's a solution you don't need a loop for, pretending the condition is that the entry in column 4 is an h.
awk -F ',' '{ if ($4 == "h") print $0",z"; else print $0","}' inp.txt > out.txt
output:
a,b,c,d,
e,f,g,h,z
i,j,k,l,
Upvotes: 2