Isso (adaptado de aqui ) deve fazer o que você precisa, embora o de Perl do @rici seja muito mais simples:
$ sed -r ':a;s/(("[0-9,]*",?)*"[0-9,]*),//;ta; s/""/","/g;
s/"([0-9]*)",?/,/g ' file
56,72,123454,x,y,"foo,a,b,bar"
56,92,1234,x,y,"foo,a,b,bar"
56,72,12345478765467,x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar",123454,
56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo"
Explicação
-
:a: define um rótulo chamadoa. -
s/(("[0-9,]*",?)*"[0-9,]*),//: Este precisa ser dividido- Antes de mais nada, use esta construção:
(foo(bar)),seráfoobareserábar. -
"[0-9,]*",?: corresponde a 0 ou mais de0-9ou,, seguido por 0 ou 1,. -
("[0-9,]*",?)*: corresponde a 0 ou mais dos acima. -
"[0-9,]*: corresponde a 0 ou mais de0-9ou,que aparecem imediatamente após"
- Antes de mais nada, use esta construção:
-
ta;: volte para o rótuloae execute novamente se a substituição foi bem sucedida. -
s/""/","/g;: pós-processamento. Substitua""por",". -
s/"([0-9]*)",?/,/g: remova todas as aspas em torno dos números.
Isso pode ser mais fácil de entender com outro exemplo:
$ echo '"1,2,3,4"' | sed -nr ':a;s/(("[0-9,]*",?)*"[0-9,]*),//;p;ta;'
"1,2,34"
"1,234"
"1234"
"1234"
Assim, enquanto você pode encontrar um número logo após uma citação e seguido por uma vírgula e outro número, junte os dois números juntos e repita o processo até que não seja mais possível.
Neste ponto, acredito que seja útil mencionar uma citação de info sed que aparece na seção descrevendo funções avançadas, como o rótulo usado acima (obrigado por descobrir se @Braiam):
In most cases, use of these commands indicates that you are probably better off programming in something like 'awk' or Perl.