LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-12-2013, 04:20 AM   #1
cristalp
Member
 
Registered: Aug 2011
Distribution: Linux Mint
Posts: 103

Rep: Reputation: Disabled
AWK: how to replace particular field or sub-string?


I want to only replace string of the last field of each line to string "B".

I did
Code:
awk '{gsub($NF, "B");print}' FILE
However, the first field in my file also contains "A", then it change it also to "B".

I tried then
Code:
awk '{sub($NF, "B");print}' FILE
It dose not replace anything in my file.

How could I do this properly? Thanks for your help.
 
Old 06-12-2013, 04:23 AM   #2
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 21,120

Rep: Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120
Try
Code:
$NF = "B"
and see if it helps.
 
Old 06-12-2013, 06:33 AM   #3
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,005

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
You may need to be clearer about what action you require.

1. syg00 is correct if you simply wish to make the last a B

2. Your current two examples are using the data stored in the last value and searching the entire line and then gsub replaces all occurrences and sub will replace the first

3. If you wish to alter the last value and change part of it to B then you need to tell the commands what to look for and place the field being looked at (NF in examples) after the change value, example:
Code:
gsub(/old_value/, "B", $NF)
 
Old 06-13-2013, 09:43 AM   #4
cristalp
Member
 
Registered: Aug 2011
Distribution: Linux Mint
Posts: 103

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by grail View Post
You may need to be clearer about what action you require.

1. syg00 is correct if you simply wish to make the last a B

2. Your current two examples are using the data stored in the last value and searching the entire line and then gsub replaces all occurrences and sub will replace the first

3. If you wish to alter the last value and change part of it to B then you need to tell the commands what to look for and place the field being looked at (NF in examples) after the change value, example:
Code:
gsub(/old_value/, "B", $NF)
Thanks grail, I tried your code. Yes, it works. BUT, it changed the format of the line that has B at the last field. That means the number of spaces between each field are different after I change it. Is there any way to use gsub and keep the format at the same time?
 
Old 06-13-2013, 10:29 AM   #5
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,005

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Unfortunately this is a side affect of setting the positional item to a new value. Perhaps if you gave us an example of what you are attempting we could help with a better solution?
 
Old 06-13-2013, 03:11 PM   #6
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Mint 17.3
Posts: 1,881

Rep: Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660
With this InFile ...
Code:
Apple1  Apple2   Apple3 Apple4
Pear1     Pear2  Pear3    Pear4
Cherry1 Cherry2 Cherry3  Cherry4
... this sed ...
Code:
sed 's/\(.* \)\([^:graph:].*\)/\1B/' $InFile >$OutFile
... produced this OutFile ...
Code:
Apple1  Apple2   Apple3 B
Pear1     Pear2  Pear3    B
Cherry1 Cherry2 Cherry3  B
Daniel B. Martin

Last edited by danielbmartin; 06-13-2013 at 03:24 PM. Reason: Improved code
 
Old 06-14-2013, 01:43 PM   #7
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Quote:
Originally Posted by cristalp View Post
Thanks grail, I tried your code. Yes, it works. BUT, it changed the format of the line that has B at the last field. That means the number of spaces between each field are different after I change it. Is there any way to use gsub and keep the format at the same time?
Yes, this is a side-effect of the way awk works. It only keeps the original spacing if the line remains unaltered (e.g. print $0). If any changes are made to the line, then the full effect of field-splitting takes over, and the output is printed with the value of the OFS (output field separator) variable between each field instead.

So your options are to either set OFS to the same character as FS (or whatever you want), or manually format the output in print/printf.

Code:
$ echo 'foo  bar   baz' | awk '{ print }'
foo  bar   baz

$ echo 'foo  bar   baz' | awk '{ $2="bam" ; print }'
foo bam baz

$ echo 'foo  bar   baz' | awk -v OFS='   ' '{ $2="bam" ; print }'
foo   bam   baz
 
Old 06-14-2013, 06:27 PM   #8
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 21,120

Rep: Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120
I ran into the (re)formatting issue when dealing with columnar data - with page headings. As the data came down from a mainframe and has to be sent back I changed my approach.
Leave the data you get the way the client sent it, and tack more field(s) on the end of lines.

Easy to do, within my control, and the customer agreed.
KISS, but YMMV.
 
Old 06-15-2013, 03:23 AM   #9
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,005

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
I would like to make a slight adjustment to David's information:
Quote:
If any changes are made to the line, then the full effect of field-splitting takes over, and the output is printed with the value of the OFS (output field separator) variable between each field instead.
This should be if any change is made to the pieces of the original line, as a change to $0 itself does not incur this result:
Code:
$ echo 'foo  bar   baz' | awk '{sub(/bar/,"bam");print}'

# as oppsoed to

$ echo 'foo  bar   baz' | awk '{sub(/bar/,"bam",$2);print}'
As the first example is using the complete line in tact, ie $0, any formatting is retained, but once you change a field ($2 in example), then OFS is introduced to the output
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Replace a particular field in a particular line with user input using awk Divyavec Linux - Newbie 7 08-09-2012 09:23 AM
[SOLVED] Using Awk to replace the 6th Field of a string metallica1973 Programming 4 08-06-2012 02:48 PM
Replace a field for a whole line in the same file, with awk. amwink Programming 12 11-13-2009 06:51 AM
awk to replace particular field vgr12386 Programming 9 06-05-2009 07:15 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 11:03 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration