2

I have a example dataset separated by semicolon as below;

123;IZMIR;ZMIR;123
abc;ANKAR;aaa;999
AAA;ZMIR;ZMIR;bob
BBB;ANKR;RRRR;ABC

I would like to replace values in a specified column. Lets say I want to change "ZMIR" AS "IZMIR" but only for the third column, the ones on the second column must stay the same.

Desired output is;

123;IZMIR;IZMIR;123
abc;ANKAR;aaa;999
AAA;ZMIR;IZMIR;bob
BBB;ANKR;RRRR;ABC

I tried;

sed 's/;ZMIR;/;IZMIR;/' file.txt

the problem is that it changes all the values on the file not just the 3rd one.

I also tried;

awk -F";" '{gsub("ZMIR",";IZMIR;",$2)}1'

and here it specifies the column but, it somehow adds spaces;

123 I;IZMIR; ZMIR 123
abc;ANKAR;aaa;999
AAA ;IZMIR; ZMIR bob
BBB;ANKR;RRRR;ABC

5 Answers5

2

sed doesn't know about columns, awk does (but in awk they're called "fields"):

awk 'BEGIN{FS=OFS=";"} $3=="ZMIR"{$3="IZMIR"} 1' file

Note that since the above is doing a literal string search and replace, you don't have to worry about regexp or backreference metacharacters in the search or replacement strings, unlike in a sed solution (see https://stackoverflow.com/a/29626460/1745001).

wrt what you tried previously with awk:

awk -F";" '{gsub("ZMIR",";IZMIR;",$2)}1'

That says: find "ZMIR" in the 2nd semi-colon-separated field and replace it with ";IZMIR;" and also change every existing ";" on the line to a blank character.

To learn awk, read the book Effective Awk Programming, 4th Edition, by Arnold Robbins.

Community
  • 1
  • 1
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • it works! thank you very much. Is it also possible to save the result or do I have to redirect it? –  Feb 02 '17 at 14:24
  • Gnu awk has a `-i inplace` option but in general `awk 'script' file > tmp && mv tmp file` works just fine for every UNIX command. – Ed Morton Feb 02 '17 at 14:35
0

If you exactly know where the word to replace is located and how many of them are in that line you could use sed with something like:

sed '3 s/ZMIR/IZMIR/2'

With the 3 in the beginning you are selecting the third line and with the 2 in the end the second occurrence. However the awk solution is a better one. But just that you know how it works in sed ;)

JFS31
  • 518
  • 5
  • 13
  • it works only if you know exactly what and where it is int the file. If line is (ex:)`ddd;IZMIR;IZMIR;bad` it failed. and OP specify '*sample of data*' and '*replace values in a specified column*' – NeronLeVelu Feb 02 '17 at 14:39
0

This might work for you (GNU sed):

sed -r 's/[^;]+/\n&\n/3;s/\nZMIR\n/IZMIR/;s/\n//g' file

Surround the required field by unique markers then replace the required string (plus markers) by the replacement string. Finally remove the unique markers.

potong
  • 55,640
  • 6
  • 51
  • 83
0

Perl on Command Line

Input

123;IZMIR;ZMIR;123  
000;ANKAR;aaa;999  
AAA;ZMIR;ZMIR;bob  
BBB;ANKR;RRRR;ABC    

$. == 1 means first row it does the work only for this row So second row $. == 2
$F[0] means first column and it only does on this column So fourth column $F[3]
-a -F\; means that delimiter is ;

what you want
perl -a -F\; -pe 's/$F[0]/***/ if $. == 1' your-file

output

***;IZMIR;ZMIR;123  
abc;ANKAR;aaa;999  
AAA;ZMIR;ZMIR;bob  
BBB;ANKR;RRRR;ABC   

for row == 2 and column == 2
perl -a -F\; -pe 's/$F[1]/***/ if $. == 2' your-file

123;IZMIR;ZMIR;123  
abc;***;aaa;999  
AAA;ZMIR;ZMIR;bob  
BBB;ANKR;RRRR;ABC    

Also without -a -F
perl -pe 's/123/***/ if $. == 1' your-file

output

***;IZMIR;ZMIR;123  
abc;ANKAR;aaa;999  
AAA;ZMIR;ZMIR;bob  
BBB;ANKR;RRRR;ABC   

If you want to edit you can add -i option that means Edit in-place And that's it, it simply find, replace and save in the same file
perl -i -a -F\; and so on

Shakiba Moshiri
  • 21,040
  • 2
  • 34
  • 44
-1

You need to include some absolute references in the line:

  • ^ for beginning of the line
  • unequivocal separation pattern
  • ^.*ZMIR and [^;]*;ZMIR give different values where first take everything before ZMIR and sed take the longest possible

Specific

sed 's/^\([^;]*;[^;]*;\)ZMIR;/\1IZMIR;/' YourFile

generic where Old and New are batch variable (Remember, this is regex value so regex rules to apply like escaping some char)

#Old='ZMIR'
#New='IZMIR'

sed 's/^\(\([^;]*;\)\{2\}\)'${Old}';/\1'${New}';/' YourFile

In this simple case sed is an alternative, but awk is better for a complex or long line.

agc
  • 7,973
  • 2
  • 29
  • 50
NeronLeVelu
  • 9,908
  • 1
  • 23
  • 43