How to write a sed function that finds a character not between quotes on OS X

Viewed 96

I'm trying to write a sed command that replaces all commas that are not between quotes with the word 'linux'. Unfortunately, it's not working and I would like to know why.

My command:

sed -i '.bak' -e 's;,(?=([^"]*"[^"]*")*[^"]*$);linux;g' file.txt

I tested the regex (/,(?=([^"]*"[^"]*")*[^"]*$)/g) between the semicolons on regexr.com and it's working as expected. When running my command the file does not change. I'm running this command from macOS that's why I specify the backup extension.

file.txt contains the following text and the first comma should be replaced with 'linux': a matching comma, "a non-matching comma,"

Using sed -i '.bak' -e 's;comma;linux;g' file.txt works fine and replaces both words with 'linux'.

Let me know how I could fix this? Thanks in advance!

1 Answers

As usual, when it comes to matching some pattern in specific contexts, it makes sense to use perl instead of sed:

perl -i -pe 's/"[^"]*"(*SKIP)(*F)|,/linux/g' file

The regex matches

  • "[^"]*" - a ", zero or more chars other than " and then a "
  • (*SKIP)(*F) - omit the found match and force the regex engine to start searching for another match at the location where the index was located
  • | - or
  • , - a comma.

See an online demo:

s='one , two , "three , four" , five'
perl -pe 's/"[^"]*"(*SKIP)(*F)|,/linux/g' <<< "$s"
# => one linux two linux "three , four" linux five
Related