sed replace in-line a specific column number value at a specific line number

linux, sed, shell

Solution

Here is one way:

$ sed '/^username4/{s/ [^ ]*/ anything/3}' file
username1 20130310 enabled 20130310 enabled
username2 20130310 enabled 20130321 disabled
username3 20130320 disabled 20130321 enabled
username4 20130310 disabled anything disabled

# store changes back to the file 
$ sed -i '/^username4/{s/ [^ ]*/ anything/3}' file

But avoiding `awk` because `sed` has the `-i` option isn't a good reason. `awk` is more suited to working with this kind of problem.

$ awk '$1=="username4"{$4="anything"}1' file
username1 20130310 enabled 20130310 enabled
username2 20130310 enabled 20130321 disabled
username3 20130320 disabled 20130321 enabled
username4 20130310 disabled anything disabled

# store changes back to the file
$ awk '$1=="username4"{$4="anything"}1' file > tmp && mv tmp file

With `awk` you can easily do field comparison and editing, using shell variable isn't a quoting nightmare and understanding scripts you wrote only yesterday isn't and issue unlike with `sed`:

$ linenumber=4

$ newvalue=anything 

$ awk 'NR==n{$4=a}1' n=$linenumber a=$newvalue file 
username1 20130310 enabled 20130310 enabled
username2 20130310 enabled 20130321 disabled
username3 20130320 disabled 20130321 enabled
username4 20130310 disabled anything disabled

$ awk 'NR==n{$4=a}1' n=$linenumber a=$newvalue file > tmp && mv tmp file

Problem

I have a 5 columns csv file (space separated) like this : ``` username1 20130310 enabled 20130310 enabled username2 20130310 enabled 20130321 disabled username3 20130320 disabled 20130321 enabled username4 20130310 disabled 20130310 disabled ``` I'am trying to change the value of the 4th column for `username4`. My script already gets the line number and the new value to store for `username4` : so I would like to replace column 4 value with `$newValue` at line number `$lineNumber`. In my sample: ``` newValue=anything lineNumber=4 ``` So that it will render: ``` username1 20130310 enabled 20130310 enabled username2 20130310 enabled 20130321 disabled username3 20130320 disabled 20130321 enabled username4 20130310 disabled anything disabled ``` I plan to use `sed` instead of `awk` because with `sed` we can do in-line changes with `-i`

Original source