LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   updating a field in a record through AWK (https://www.linuxquestions.org/questions/programming-9/updating-a-field-in-a-record-through-awk-782003/)

suresh.chola 01-13-2010 11:37 AM

updating a field in a record through AWK
 
I have a record and need to update a particular field in that record.

Here is my code:
TargetFld=`echo TargetRec|cut -d',' -f3`
TargetFld=`sed -e s/cycle/$cycle/ $TargetLoc`
TargetRec=`echo $1|awk -F ',' '{print $1","$2","$TargetLoc","$4","$5","$6","$7","$8","$9","$10","$11}'`

As you can see i am just printing all fields one by one...
First of all is this correct approach?
Is there any better way to update the 3rd field in a record.

Thanks in Advance
Suresh

Tinkster 01-13-2010 02:02 PM

Hi,

Your only problem is that you can't use the shell variables
directly in the awk statement.

Read "man awk", search for "- v".


Cheers,
Tink

colucix 01-13-2010 03:22 PM

Quote:

Originally Posted by suresh.chola (Post 3825334)
Is there any better way to update the 3rd field in a record.

Yes. Using the sub or the gsub function you can alter the content of a field. After having followed the advice by Tinkster, you can try something like:
Code:

'{sub($3,replacement,$3); print}'
In addition to the man page of awk suggested above, you can consult the GNU Awk User's Guide... a must-read! :)

suresh.chola 01-14-2010 03:12 AM

Thanks Guys.

I got my final code like this:

TargetLoc=`echo $1|cut -d',' -f3`
if [ `echo $TargetLoc|grep <year>` != "" ]; then
NewTargerRec=`echo ${$1/year/$year}`
TargetRec=$NewTargetRec
fi

However, i didn't understand few things while I am working on this.
When i tried with sub funciton like below :

str="customer,234/34,ET-Street,<year>,Active"
week=2009
Newstr=`echo $str| awk -F ',' { sub($4/$week); print`

This didnt wont as there is a problem with $week substitution.

if i give as below, it's working.
Newstr=`echo $str| awk -F ',' { sub($4/200901); print`

I heard that, in ksh and bash all the variables are global.
So, can't I use $week which is outside awk statement in the above awk statment.
Is this due to variable scoping.

And by the way, i didnt find "awk -v" option useful in my above problem.
I am sorry, am I missing something there...

Thanks for your responses guys.

Suresh

colucix 01-14-2010 10:09 AM

Quote:

Originally Posted by suresh.chola (Post 3826052)
Newstr=`echo $str| awk -F ',' { sub($4/200901); print`

Sorry, Suresh, but your code is a bit unreadable and full of syntax errors. It's difficult to provide a good reply to your questions under these condition.

Please, use CODE tags to embed your code when posting (to do that you can switch to Advanced mode, then select the lines you want to embed and press the # (hash) button in the task bar at the top of the text box). This will also preserve indentation and spacing. Furthermore, try to copy/paste the lines from your terminal or from your script to avoid typos as possible.

suresh.chola 01-14-2010 11:59 PM

Sorry for that, Colucix.

I was in bit hurry and didn't paste the actual code.
Thanks for your tips.

Here is the code:
Code:

$ more test1.sh
str="customer,234/34,ET-Street,<year>,Active"
week=2009
newstr=`echo $str|awk -F ',' '{ sub($4,200901); print}'

$ sh test1.sh
$ echo $newstr
customer,234/34,ET-Street,200901,Active

Here is the second code:
Code:

$more test2.sh
str="customer,234/34,ET-Street,<year>,Active"
week=2009
newstr=`echo $str|awk -F ',' '{ sub($4,$week); print}'`

$sh test2.sh
$ echo $newstr
customer,234/34,ET-Street,customer,234/34,ET-Street,<year>,Active,Active

My question is: Why $week is not giving the desired result in the test2. If i give the value of $week then it is working fine as shown in test1.

Is there any scoping(Global and Local) of the variables in bash.

Please let me know if you need more explanation, I am more than happy to provide.

Thanks,
Suresh

David the H. 01-15-2010 02:25 AM

It's because $week in awk is not the same variable as $week in bash.

You have to understand that awk has it's own, slightly different, variable system. In addition, even as a bash variable, the ' hard-quoting turns off substitution for it.

As tinkster said, you have to use the -v option (or careful quoting), in order to import the bash variable into the awk statement.

This awk tutorial is a recommended read. Give it a whirl.
http://www.grymoire.com/Unix/Awk.html

David the H. 01-15-2010 02:59 AM

For the record, this should fix your script.
Code:

str="customer,234/34,ET-Street,<year>,Active"
week=2009
newstr=$(echo "$str"|awk -F ',' -v "wk=$week" '{ sub($4,wk); print}')

Unlike bash, awk variables are substituted by name only, with no '$' in front of them. When the dollar sign is included, awk will print the contents of the column (or whatever the substituted value refers to) from the input text. Using $wk in the above would make awk try to print the contents of column number 2009, for example.

Also note the (") soft-quoting of the -v value. Unlike single-quotes, double-quotes allow for bash variable substitution.

Finally, backticks (`) are discouraged in bash these days. The $() form is recommended as more robust and readable. See here.

colucix 01-15-2010 04:26 PM

David the H. already provided an exhaustive explanation (thanks). Just a little add-on to explain why you got a weird result in the second test.

The syntax of the sub function in awk is:
Code:

sub(regexp, replacement [, target])
as you can see you may pass two or three arguments. You chose to pass only two, so that the substitution is applied to the whole line (record in awk).

The regexp, that is the regular expression that matches the part of the string you want to substitute is $4 in your statement, that is "<year>".

The replacement is $week, that in awk code - as David pointed out - is a reference to a field. week in this case is a variable to which you didn't assign any value (inside the awk code), so that it retains a value of 0. Therefore, the resulting substitution is:
Code:

sub($4,$0)
which means substitute the text matching the fourth field with the whole record. The result is indeed:
Code:

customer,234/34,ET-Street,customer,234/34,ET-Street,<year>,Active,Active
where the substituted part is highlighted in blue. Hope this helps. Cheers! :)

suresh.chola 01-18-2010 08:07 AM

All your answers helped me a lot.
Thanks a million guys.


All times are GMT -5. The time now is 01:09 AM.