perl -pe 's/(".*?")/do{$a = $1;$&; $a =~ s: +:,:g; $a}/ge;'
Essentially, this is just a global regex replacement s/regex/replacement/g.
The regex is ".*?", it matches every substring that starts with " and ends with the next following ".
The tricky parts are:
- The replacement is not a string, but an expression that is evaluated.
(That's the meaning of the
emodifier afterg.) - The expression that is evaluated is again a global regex replacement
s:regex:replacement:gthat replaces any non-empty sequence of spaces by a comma. (We cannot use the same delimiter as in the outer replacement, so we use:instead of/.) - In order to execute the inner regex replacement, we have to assign the matched substring of the outer replacement
$1$&to some other variable$a, then perform the inner replacement on$a, and finally print$a.
With a sufficiently recent perl version, the assignment to an auxiliary variable can be avoided. Using the r modifier, the inner replacement can be performed directly on a copy of the matched substring $& (thanks to Stéphane Chazelas):
perl -pe 's/".*?"/$&=~s: +:,:gr/ge;'