Java регулярное выражение для соответствия французскому числу с плавающей запятой не совпадает с пустым пространством - PullRequest
0 голосов
/ 08 декабря 2018

Я пишу простую проверку для чисел BigDecimal на английском, испанском и французском языках.Я хочу принять простые числа, такие как (1234,56 или 1234,56 в зависимости от локали десятичного разделителя) и отформатированные числа (1234,56 для английского языка, 1,234,56 для испанского или 1 234,56 для французского).Я сделал это с английским и испанским языками, и я успешно проверил это, но это не с французским.

public static void main(final String[] args) {
    System.out.println( "es 1.234.567,89 : " + "1.234.567,89".matches("(((\\d{1,3})([.]\\d{3})*)|(\\d+))([,]\\d+)?") );
    System.out.println( "en 1,234,567.89 : " + "1,234,567.89".matches("(((\\d{1,3})([,]\\d{3})*)|(\\d+))([.]\\d+)?") );
}

Вывод:

es 1.234.567,89 : true
en 1,234,567.89 : true

Но когда я пытаюсь это сделатьс французским групповым разделителем, валидация Falis.

    public static void main(final String[] args) {
    System.out.println( "fr 1 234 567,89 : " + "1 234 567,89".matches("(((\\d{1,3})([ ]\\d{3})*)|(\\d+))([,]\\d+)?") );
}

Вывод:

fr 1 234 567,89 : false

Это также не удается:

    public static void main(final String[] args) {
    System.out.println( "fr 1 234 567,89 : " + "1 234 567,89".matches("(((\\d{1,3})(\\s\\d{3})*)|(\\d+))([,]\\d+)?") );
}

Вывод:

fr 1 234 567,89 : false

Есть предложения?

Ответы [ 2 ]

0 голосов
/ 08 декабря 2018

Вот регулярное выражение, которое точно соответствует всем вашим форматам.

^\d{1,3}(?:([., ])?\d{3})?(?:\1\d{3})*(?:(?!\1)[,.]\d+)?$

Объяснение:

  • ^ -> Соответствует началу строки
  • \d{1,3} -> Соответствует от одной до трех цифр
  • (?:([., ])?\d{3})? -> Здесь ([., ]) захватывает либо точку, запятую или пробел и помещает в группу 1 для обратной ссылки для неразрешая его как разделитель десятичных чисел, и этот набор символов необязателен, чтобы соответствовать простой версии чисел.Во-вторых, \d{3} следует за трехзначными числами, и вся эта группа необязательна для сопоставления целых чисел, в которых нет точек, запятых или пробелов.
  • (?:\1\d{3})* -> Эта часть предназначена для сопоставления точек,запятая или пробел, все, что было захвачено в group1, за которым следуют три цифры, и это может повторяться ноль или более раз.
  • (?:(?!\1)[,.]\d+)? -> Наконец, это захватывает десятичную часть, где отрицательный взгляд вперед (?!\1) не делаетразрешить то, что было записано в group1, но разрешить запятую или точку, за которой следуют одна или несколько цифр, которые будут частью десятичного числа
  • $ -> Соответствует концу ввода

Это соответствует

1.234.567,89
1.234.567
1.234
24
1234.56
1234
1,234,567.89
1 234 567,89
1 234 567,89

И не соответствует

1.234.567.89
12.234.
1,234,567,89
1,234.567.89
1 234.567,89

Демо

Ваш код Java,

System.out.println("es 1.234.567,89 : "
        + "1.234.567,89".matches("^\\d{1,3}(?:([., ])\\d{3})?(?:\\1\\d{3})*(?:(?!\\1)[,.]\\d+)?$"));
System.out.println("en 1,234,567.89 : "
        + "1,234,567.89".matches("^\\d{1,3}(?:([., ])\\d{3})?(?:\\1\\d{3})*(?:(?!\\1)[,.]\\d+)?$"));
System.out.println("fr 1 234 567,89 : "
        + "1 234 567,89".matches("^\\d{1,3}(?:([., ])\\d{3})?(?:\\1\\d{3})*(?:(?!\\1)[,.]\\d+)?$"));
System.out.println("fr 1 234 567,89 : "
        + "1 234 567,89".matches("^\\d{1,3}(?:([., ])\\d{3})?(?:\\1\\d{3})*(?:(?!\\1)[,.]\\d+)?$"));
System.out.println("1234.56: "
        + "1 234 567,89".matches("^\\d{1,3}(?:([., ])\\d{3})?(?:\\1\\d{3})*(?:(?!\\1)[,.]\\d+)?$"));
System.out.println("1234: "
        + "1 234 567,89".matches("^\\d{1,3}(?:([., ])\\d{3})?(?:\\1\\d{3})*(?:(?!\\1)[,.]\\d+)?$"));

Отпечатки,

es 1.234.567,89 : true
en 1,234,567.89 : true
fr 1 234 567,89 : true
fr 1 234 567,89 : true
1234.56: true
1234: true
0 голосов
/ 08 декабря 2018

Вы можете использовать java.text.NumberFormat, в котором уже есть встроенные правила для разных локалей.

    System.out.println( NumberFormat.getInstance(Locale.ENGLISH).parse("123,456.56") );
    System.out.println( NumberFormat.getInstance(Locale.FRENCH).parse("123 456,56") );
    System.out.println( NumberFormat.getInstance(new Locale("es-es")).parse("123.456,56") );
...