Estos casos deben coincidir con:

1.23
1
1,
1.2,4
1.23, 4
1.23, 4,
1, 2.34
1.

Estos casos no deberían:

1,,
1.234

Por lo tanto, puede haber coma o punto final, cero o un espacio después de la coma. Los números pueden ser enteros o flotantes con hasta dos fracciones.

He hecho esta expresión regular, pero falla en números con más de dos fracciones: https://regex101.com/r/CLTP2j/75

/^(?:\d+(?:\.[\d{1,2}]*)?|\.[\d{1,2}]+)(?:,[\s]?(?:\d+(?:\.[\d{1,2}]*)?|\.[\d{1,2}]+))*$/
1
catchall 7 feb. 2020 a las 13:47

2 respuestas

La mejor respuesta

Use la siguiente expresión regular:

^\d+(?:\.\d{0,2})?(?:,\s*\d+(?:\.\d{0,2})?)*,?$

Demo

En lugar de dar el desglose completo detallado (e ilegible) típico del patrón que utilicé, explicaré un requisito más simple. Supongamos que desea validar una lista CSV de letras mayúsculas, p.

A,B,C

El patrón que usarías es:

^[A-Z](?:,[A-Z])*,?$

Tenga en cuenta que el término a la derecha dice permitir cero o más adiciones de coma seguidas de otra letra. Su requisito también permite una coma final, por lo que el patrón anterior también lo incluye.

-1
Tim Biegeleisen 7 feb. 2020 a las 10:59

Si su objetivo es determinar si una cadena tiene la forma correcta, y no necesariamente usar una expresión regular aplicada a toda la cadena para hacer esa determinación, puede realizar dos pasos, empleando las siguientes expresiones regulares:

r1 = /(?<!,), ?/
r2 = /^\d+(?:\.\d{,2})?$/

Los pasos son:

  • use r1 para dividir la cadena en una o más subcadenas
  • determinar si todas las subcadenas coinciden con r2

r1 lee, "coincide con una coma seguida de un espacio como máximo y no precedida por una coma.

r2 dice: "coincide con uno o más dígitos al comienzo de la cadena, opcionalmente seguido por un punto decimal y luego 0, 1 o 2 dígitos, seguido por el final de la cadena".

En Ruby, por ejemplo, se obtiene lo siguiente:

arr =<<~END.split("\n")
1.23
1
1,
1.2,4
1.23, 4
1.23, 4,
1, 2.34
1,  2.34
1,,
1.234
END
  #=> ["1.23", "1", "1,", "1.2,4", "1.23, 4", "1.23, 4,", "1, 2.34",
  #    "1,  2.34", "1,,", "1.234"] 
arr.each do |s|
  a = s.split r1
  result = a.all? { |t| t.match? r2 } ? "(Match)" : "(No match)"
  puts "%-9s: %-14s %s" % [s, a.inspect, result]
end
string     array          match?
---------------------------------
1.23     : ["1.23"]       (Match)
1        : ["1"]          (Match)
1,       : ["1"]          (Match)
1.2,4    : ["1.2", "4"]   (Match)
1.23, 4  : ["1.23", "4"]  (Match)
1.23, 4, : ["1.23", "4"]  (Match)
1, 2.34  : ["1", "2.34"]  (Match)
1,  2.34 : ["1", " 2.34"] (No match)
1,,      : ["1", ","]     (No match)
1.234    : ["1.234"]      (No match)

Una ventaja importante de este enfoque es que probar es mucho más fácil que probar una sola expresión regular contra toda la cadena, ya que r1 y r2 se pueden probar por separado. Este enfoque también puede adaptarse más fácilmente a los requisitos cambiantes en el futuro.

-1
Cary Swoveland 9 feb. 2020 a las 19:14