Expresión regular para analizar pares de nombre y nombre

¿Puede alguien proporcionar una expresión regular para analizar pares de nombre / valor de una cadena? Los pares están separados por comas, y el valor opcionalmente puede estar entre comillas. Por ejemplo:

AssemblyName=foo.dll,ClassName="SomeClass",Parameters="Some,Parameters" 

  • No hay escapatoria:

     /([^=,]*)=("[^"]*"|[^,"]*)/ 
  • Escape de comillas dobles para la clave y el valor:

     /((?:"[^"]*"|[^=,])*)=((?:"[^"]*"|[^=,])*)/ key=value,"key with "" in it"="value with "" in it",key=value" "with" "spaces 
  • Backslash string escape:

     /([^=,]*)=("(?:\\.|[^"\\]+)*"|[^,"]*)/ key=value,key="value",key="val\"ue" 
  • Escape de barra invertida completa:

     /((?:\\.|[^=,]+)*)=("(?:\\.|[^"\\]+)*"|(?:\\.|[^,"\\]+)*)/ key=value,key="value",key="val\"ue",ke\,y=val\,ue 

Editar: se agregaron alternativas de escape.

Edit2: se agregó otra alternativa de escape.

Tendría que limpiar las claves / valores eliminando los caracteres de escape y las comillas circundantes.

Buena respuesta de MizardX. Problemas menores: no permite espacios en torno a nombres, etc. (que pueden no importar), y recoge las comillas, así como el valor citado (que también puede no importar), y no tiene un mecanismo de escape para incrustar comillas dobles en el valor citado (que, una vez más, puede no importar).

Tal como está escrito, el patrón funciona con la mayoría de los sistemas de expresión regular extendida. Arreglar los problemas probablemente requeriría un descenso en, digamos, Perl. Esta versión utiliza comillas dobles para escapar, por lo tanto, a = “a” “b” genera un valor de campo ‘a’ ‘b’ (que no es perfecto, pero que luego se puede corregir con bastante facilidad):

 /\s*([^=,\s]+)\s*=\s*(?:"((?:[^"]|"")*)"|([^,"]*))\s*,?/ 

Además, tendrías que usar $ 2 o $ 3 para recolectar el valor, mientras que con la respuesta de MizardX, simplemente usar $ 2. Por lo tanto, no es tan fácil o agradable, pero cubre algunos casos extremos. Si la respuesta más simple es adecuada, úselo.

Secuencia de comandos de prueba:

 #!/bin/perl -w use strict; my $qr = qr/\s*([^=,\s]+)\s*=\s*(?:"((?:[^"]|"")*)"|([^,"]*))\s*,?/; while (<>) { while (m/$qr/) { print "1= $1, 2 = $2, 3 = $3\n"; $_ =~ s/$qr//; } } 

Esto indica que $ 2 o $ 3 están indefinidos, con precisión.

Así es como lo haría si puedes usar Perl 5.10 .

 qr /
   (? 
     (?
       [^ =, \\]
     |
       (?&escapar)
     ) ++ # Evitar claves nulas
   )

   \ s * +
   =
   \ s * +

   (? 
     (? "ed)
   |
     (?
       [^ =, \ s \\]
     |
       (?&escapar)
     ) ++ # Prevenir el valor nulo (usar comillas para eso)
   )

   (?(DEFINIR)
     (?  \\.)
     (? 
       "
         (?
           (?&escapado)
         |
           [^ "\\]
         ) * +
       "
     )
   )
 /X

Se accederá a los elementos a través de %+ .

perlretut fue muy útil para crear esta respuesta.