spiroskafk
spiroskafk

Reputation: 1

Save changes to a file AWK/SED

I have a huge text file delimited with comma.

19429,(Starbucks),390 Provan Walk,Glasgow,G34 9DL,-4.136909,55.872982 

The first one is a unique id. I want the user to enter the id and enter a value for one of the following 6 fields in order to be replaced. Also, i'm asking him to enter a 2-7 value in order to identify which field should be replaced.

Now i've done something like this. I am checking every line to find the id user entered and then i'm replacing the value.

awk -F ',' -v elem=$element -v id=$code -v value=$value '{if($1==id) {if(elem==2) { $2=value } etc }}' $path

Where $path = /root/clients.txt

Let's say user enters "2" in order to replace the second field, and also enters "Whatever". Now i want "(Starbucks)" to be replaced with "Whatever" What i've done work fine but does not save the change into the file. I know that awk is not supposed to do so, but i don't know how to do it. I've searched a lot in google but still no luck.

Can you tell me how i'm supposed to do this? I know that i can do it with sed but i don't know how.

Upvotes: 0

Views: 1235

Answers (2)

Ed Morton
Ed Morton

Reputation: 203254

Newer versions of GNU awk support inplace editing:

awk -i inplace -v elem="$element" -v id="$code" -v value="$value" '
    BEGIN{ FS=OFS="," } $1==id{ $elem=value } 1
' "$path"

With other awks:

awk -v elem="$element" -v id="$code" -v value="$value" '
    BEGIN{ FS=OFS="," } $1==id{ $elem=value } 1
' "$path" > /usr/tmp/tmp$$ &&
mv /usr/tmp/tmp$$ "$path"

NOTES:

  1. Always quote your shell variables unless you have an explicit reason not to and fully understand all of the implications and caveats.
  2. If you're creating a tmp file, use "&&" before replacing your original with it so you don't zap your original file if the tmp file creation fails for any reason.
  3. I fully support replacing Starbucks with Whatever in Glasgow - I'd like to think they wouldn't have let it open in the first place back in my day (1986 Glasgow Uni Comp Sci alum) :-).

Upvotes: 3

Floris
Floris

Reputation: 46365

awk is much easier than sed for processing specific variable fields, but it does not have in-place processing. Thus you might do the following:

#!/bin/bash
code=$1
element=$2
value=$3
echo "code is $code"
awk -F ',' -v elem=$element -v id=$code -v value=$value 'BEGIN{OFS=",";} /^'$code',/{$elem=value}1' mydb > /tmp/mydb.txt
mv /tmp/mydb.txt ./mydb

This finds a match for a line starting with code followed by a comma (you could also use ($1==code)), then sets the elemth field to value; finally it prints the output, using the comma as output field separator. If nothing matches, it just echoes the input line.

Everything is written to a temporary file, then overwrites the original.

Not very nice but it gets the job done.

Upvotes: 2

Related Questions