I have a file that uses | as a delimiter. Some of the records have empty cell as || (nothing inside). I am trying to replace them with |""| with following sed command:

sed -i 's/\|\|/\|""|/g' file

But the result wasn't what I expected.

Input file


Desired output:


Note that the beginning and ending of records doesn't have "|"

Any help would be appreciated.

  • 1
    BTW: In sed, alternation is \| not |, so you don't actually want to escape those |s. – derobert Oct 15 '14 at 16:45
  • This is a strange thing to do for a CSV file: usually either all the fields are quoted, or only the ones that contain the separator are quoted. Your question makes me thing the process that consumes your data is broken. – glenn jackman Oct 15 '14 at 17:01
  • Your question asks "How?", but I suspect that you're wondering "Why?" It may help you to understand if you try echo cat | sed 's/a/aa/g' or echo caaat | sed 's/a/aa/g'. You'll end up with caat or caaaaaat, respectively, and not an infinite loop -- because, when sed makes a substitution with an s command, it doesn't look in the new (replacement) text for further matches. E.g., when it changes cat to caat, it doesn't say, "Oh! There are two more as that I need to match and replace." cont... – G-Man Says 'Reinstate Monica' Oct 16 '14 at 0:58
  • cont... The point is, when it changes D|| to D|""|, it doesn't consider the | after the quotes as a candidate for further replacement, so the ||E doesn't change. – G-Man Says 'Reinstate Monica' Oct 16 '14 at 0:58

Just repeat the substitution until output doesn't change:

$ echo 'A|B|C|D|||E' | sed ':X;s/||/|""|/g;tX'


  • :X sets the label X
  • t X go to label X if s/// was successful

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.