0

I have to replace all occurrences of the vertical bar character | with a comma , when they appear between [ and ] characters, on each line of a file.

Let's say I have the below string in the file:

wah wah| [go great|no great|so great] | wah wah | [go great|no great|so great]

I want my output to be like below:

wah wah| [go great,no great,so great] | wah wah | [go great,no great,so great]

Note that there can be multiple [...] pairs.  Vertical bars between the first ] and the second [ should not be changed.

How I can achieve this using shell commands? I tried several ways like below, but nothing worked.

sed '/[/,/]/s/|/,/g' abcd.csv
2

Do

sed ': loop; s/\(\[[^][]*\)|\([^][]*\]\)/\1,\2/; t loop' input_file

What’s up?

  • : loop is a label for looping; I’ll use it in a moment.
  • s/\(\[[^][]*\)|\([^][]*\]\)/\1,\2/ replaces one | that appears between [ and ] with a comma.  Broken down:

    s/  \(  \[  [^][]  *  \)  |  \(  [^][]  *  \]  \)  /  \1,\2  /
    
    • \(\) delimits a search & replace group.  Given a [] with a | between them, this matches the [ up to (but not including) the (last) | as one group, and everything after the | up through (including) the ] as a second group.
    • \[ matches a literal [.
    • [^][] matches any character other than [ or ].  It breaks down as
      [  ^  ][  ]
      i.e., an instance of
      [^characters_to_not_match]
    • * — zero or more characters other than [ or ].
    • \) — end of group; discussed above.
    • | is a literal | (the one we want to replace).
    • The second half of the regular expression is almost the same as the first half: match a group consisting of zero or more characters other than [ or ], followed by a ].
    • Then replace all that with the first group, a comma, and the second group.  Since everything in the matched string is in one of the groups, except for the |, this functionally replaces the \ with the ,.
  • t loop — test/transfer.  If the s command found a match and made a substitution, go back to the label and try again (because the s command replaces only one | at a time).  If it didn’t find a match, terminate the command script and go on to the next line.

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.