AWK: how to replace particular field or sub-string?
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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:
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?
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?
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.
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.
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
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.