I have a file that has columns seperated by a semi column(;) and I want to change all occurrences of a word in a particular column only to another word. The column number differentiates based on the variable that holds the column number. The word I want to change is stored in a variable, and the word I want to change to is stored in a variable too.
I tried
sed -i "s/<$word>/$wordUpdate/g" $anyFile
I tried this but it changed all occurrences of word in the whole file! I only want in a particular column
the number of column is stored in a variable called numColumn
and the columns are seperated by a semi column ;
3
Answers
It is much simpler to use
awk
for column edits, e.g. if your input looks like this:You can replace
60
in columnc
withs
with something like this:Output:
This might work for you (GNU sed):
Convert each line into a separate file where the columns are lines.
Substitute the matching line (column number) with the word for the updated word.
Reverse the conversion.
N.B. The solution relies on the GNU only
e
evaluation flag. Also theword
andupdateWord
may need to be quoted.This can be done with a little creativity…
Note that I’m using double-quotes to embed the logic. This takes a little extra care to double your
‘s on backreferences.
Explained:
lead="^([^;]*;){$((c-1))}"
^
means at the start of a record(...)
is grouping for the following{...}
which specified repetition[^;]*
mean zero or more non-semicolons$((c-1))
does the math and returns one less than the desired column; if you want to look at column 3, it returns two.^([^;]*;){$((c-1))}
at the start of the record, one-less-than-column occurrences of non-semicolons followed by a semicolonthus,
sed -E "/$lead$word;/{s/($lead)$word/\1$new/}" file
mean readfile
and on records where$word
occurs in the requested column, save everything before it, and put that stuff back, but replace$word
with$new
.Even if you MUST use
sed
, I recommend a function.In use –
No changes if no matches –
NOTE –
This logic requires trailing delimiters if you ever want to match the last field –
delimiters removed:
Otherwise you have to complicate the logic a bit.
But honestly, for field parsing, you’d be so much better served to use
awk
, or evenperl
orpython
, or for that matter abash
loop, though that’s going to be relatively slow.