Q: How to replace a word in multiple lines using sed? I am trying to edit a CSV file like this:
1:field1,field2,field3,FIELD I WANT TO REPLACE, fieldx ...
2:field1,field2,field3,FIELD I WANT TO REPLACE, fieldx ...
3:field1,field2,field3,FIELD I WANT TO REPLACE, fieldx ...
5:field1,field2,field3,FIELD I WANT TO REPLACE, fieldx ...

Can I use sed to replace searching for the pattern FIELD I WANT TO REPLACE and switching for something like :
1:field1,field2,field3,NEW FIELD, fieldx ...
2:field1,field2,field3,NEW FIELD, fieldx ...
3:field1,field2,field3,NEW FIELD, fieldx ...
5:field1,field2,field3,NEW FIELD, fieldx ...


A: The easiest is using awk:
Lets say you want to replace field 5
awk 'BEGIN{FS=OFS=","}{$5="SOME NEW TEXT"}1' file


A: based on the comment you're trying to do
$ sed -i.bak 's/,Service desk procedure1,/,Service desk procedure2,/' file

commas are there to eliminate accidental matches if the searched string exists as a substring somewhere else.  Also not setting g flag, we are restricting to one match per line.
This will do inplace replacement and the old version will be renamed with .bak suffix.

A: You might consider a proper CSV parser. For example, ruby comes with one:
ruby -rcsv -e '
  f = ARGV.shift
  # read the data
  data = CSV.read(f)
  # make your updates
  data.each {|row| row[6]="Service desk procedure2"}
  # write back to the file
  CSV.open(f, "w") {|csv| data.each {|row| csv << row}}
' file

or the perl-ish one-liner (although I understand the ruby community frowns at such)
ruby -rcsv -i.bak -ne 'CSV.parse($_) {|row| row[6]="foo"; puts CSV.generate_line(row)}' file


A: This might work for you (GNU sed):
sed 's/[^,]*/NEW FIELD/4' file

Replace the 4th occurrence of zero or more non-comma characters by the literal NEW FIELD.

A: Are you wanting just a simple find and replace?  If so, try something like this:
sed -e 's/FIELD I WANT TO REPLACE/NEW FIELD/' input_file >output_file

If you ware looking for something more, please explain further.
Hope this helps.

A: This works, but I expect more elegant solutions out there (probably awk):
#!/bin/bash

echo "1:field1,field2,field3,FIELD I WANTawef TO REPfLACE, fieldx ..." > data.txt
echo "1:field1,field2,field3,FIELD I wefaaWANT TO REPLACE, fieldx ..." >> data.txt
echo "1:field1,field2,field3,FIELD I WANT TO REPawefL ACE, fieldx ..." >> data.txt
echo "1:field1,field2,field3,FIEawefLDa I WANT TO REPLACE, fieldx ..." >> data.txt

sed -e 's/\(.:.*,.*,.*\),.*,\(.*\)/\1,NEW FIELD,\2/' data.txt

So my sed matches:


*

*.: 1 character followed by :

*.*,.*,.*: 3 columns

*,.*,: the 4th column.  I decided to include the commas in the forth column, makes it clearer to read

*.*: everything that follows the 4th column

*\1,NEW FIELD,\2: put everything before the 4th column, the new field, and everything following the 4th column.


This way there is no matching any content, this way it always works, as long as you respect the columns separated by ','.
