3

for example I have scv file which looks like

a1, b1, c1, d1
a2, b2, c2, d2
a3, b3, c3, d3

What I want to do is to replace the first comma , with the semicolon ;. The position of first comma can be variable (a in the rows n and m can have different lengths). Finally my file shall look like

a1; b1, c1, d1
a2; b2, c2, d2
a3; b3, c3, d3

The other commas have to remain. Can somebody please tell me the most simple solution?

PS my solution doesn't work: sed '/s/,/;/g' file.csv

  • 3
    Do sed 's/,/;/' file.csv satisfy you? – Costas Jul 25 '16 at 13:20
  • no, I have got next error message: sed: -e expression #1, char 7: missing command – Guforu Jul 25 '16 at 13:25
  • Do you miss quotes? – Costas Jul 25 '16 at 13:27
  • I have used already the sed command, but just with /g at the end - > sed /s/,/;/g. Your code produces by me an error message. Anyway, I'm not sure this code will change all the commas. I need to change only the firs one. – Guforu Jul 25 '16 at 13:30
  • 1
    With g sed change all commas in line, without it - just first. It cannot be true sed "s/,/;/g" do work and sed "s/,/;/" gets error. If you sence with sed try while IFS=\, read a b ; do echo "$a;$b" ; done <file.csv – Costas Jul 25 '16 at 13:37
3

Pure bash solution

while IFS=\, read -r a b ; do echo "$a;$b" ; done <file.csv

Or just for fun

paste -d\; <(cut -d, -f1 file.csv) <(cut -d, -f1 --complement file.csv)
14

The g in:

sed 's/,/;/g'

is for globally, that is to substitute all occurrences of , with ;.

If you want to do only one substitution per line, take off the g:

sed 's/,/;/'

And for completeness:

You can also specify which occurrence to substitute. For instance, to substitute only the second occurrence:

sed 's/,/;/2'

With GNU sed, you can also substitute all occurrences starting from the second one (in effect, all but the first one) with:

sed 's/,/;/2g'

To perform two substitutions, in this case:

sed 's/,/;/;s/,/;/'

Where it gets more complicated is when the pattern can match the substitution (or parts of it), for instance when substituting , with <,>. sed has no built-in mechanism to address that. You may want to use perl instead in that case:

perl -pe '$i = 0; s/,/$i++ < 2 ? "<,>" : $&/ge'

perl -pe is perl's sed mode (note that the regex syntax is different). With the e flag of the s/// operator, the replacement is considered as code. There, we replace , with <,> only when our incremented counter is < 2. Otherwise, we replace the , with itself ($& actually referring to the matched string like & in sed's s command).

You can generalise that for a range or set of substitutions. Like for 3rd to 5th and 7th to 9th:

perl -pe '$i = 0; s/,/$i++;
   $i >=3 && $i <= 5 || $i >= 7 && $i <= 9 ? "<,>" : $&/ge'

To replace only the first occurrence in the whole input (as opposed to in each line):

sed -e 's/,/;/;t done' -e b -e :done -e 'n;b done'

That is, upon the first successful substitution, go into a loop that just prints the rest of the input.

With GNU sed, you can use the pseudo address 0:

sed '0,/,/s//;/'

Note

I suppose it's a typo, but the

sed '/s/,/;/g'

command you wrote in your question is something completely different.

That's doing:

sed '/start/,/end/g'

where start is s and end is ;. That is, applying the g command (replace the pattern space with the content of the hold space (empty here as you never hold anything)) for sections of the file in between one that contains s and the next one that contains ;.

  • Note that to only replace 1st occurence in a file (not in a line) you need to do something else. See: linuxconfig.org/… – Nux Jan 10 '19 at 12:15
  • @Nux. Thanks, I've added a section about that. – Stéphane Chazelas Jan 10 '19 at 14:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.