Why are spaces delimiting, instead of FPAT

Viewed 550

I'm attempting to split strings delimited by ',' except where the ',' is in a substring enclosed by brackets. Modifying other solutions here and examples in the docs I tried this test:

awk -v FPAT='([^,]+)|(\([^\))+\))' '{
    for (i=1; i<=NF; i++) {
        printf("%s\n", $i)
    }                     
}' <<< 'one two (1one), three four (3three, 4four), five six, seven eight, nine ten eleven (8ten)'
one
two
(1one),
three
four
(3three,
4four),
five
six,
seven
eight,
nine
ten
eleven
(8ten)

The FPAT isn't overriding the default delimiter as I expected. so clearly I'm missing something.

The output I want is:

one two (1one),
three four (3three, 4four),
five six,
seven eight, 
nine ten eleven (8ten)
2 Answers

Your code does not work because,

  1. ([^,]+)|(\([^\))+\)) is an invalid regex, it has an unmatched [ in it,
  2. You say you're using mawk, but it doesn't support FPAT.

Here is the FPAT solution I've come up with

$ cat file
one two (1one), three four (3three, 4four), five six, seven eight, nine ten eleven (8ten)
$
$ awk -v FPAT='[^,(]*(\\([^)]*\\))?(, |$)' '{ for (i=1; i<=NF; ++i) print $i }' file
one two (1one),
three four (3three, 4four),
five six,
seven eight,
nine ten eleven (8ten)

Explanation of FPAT variable:

  • [^,(]* matches any number of non-comma, non-parenthesis chars,
  • \\([^)]*\\) matches any number of non-parenthesis chars surrounded by parentheses,
    • Putting this in (...)? makes this match optional.
  • (, |$) means matched field should end with a comma followed by a space, or it should be the last field in the line.

And here is how to do it in mawk

mawk '{ gsub(/[^,(]*(\([^)]*\))?, /, "&\n") }1'  file

sed could be used as well for this particular case

sed 's/[^,(]*\(([^)]*)\)\?, /&\n/g'  file

Using gnu grep:

s='one two (1one), three four (3three, 4four), five six, seven eight, nine ten eleven (8ten)'
grep -oP '\s*\K([^,(]*\([^)]*\))*[^,]*(,|$)' <<< "$s"

one two (1one),
three four (3three, 4four),
five six,
seven eight,
nine ten eleven (8ten)

If you don't have gnu grep then you may use

grep -oE '([^,(]*\([^)]*\))*[^,]*(,\s*|$)' <<< "$s"

Which will leave trailing spaces after comma.

For regex explanation see this demo.

Related