Регулярное выражение для чисел с разделителем (к примеру 1_000)

Рейтинг: 0Ответов: 1Опубликовано: 06.03.2023

Возникла задача проверять, имеет ли число разделитель, если имеет, возвращать true, соответственно сам литерал тоже должен быть валидным. Попытался сделать вот так:

const reSeparatedLiteral = /^\d(_{1,1}|\d)+\d$/
const data = [{
  str: '1_000',
  expected: true,
},{
  str: '10_00',
  expected: true,
},{
  str: '1_0_0_0',
  expected: true,
},{
  str: '_1_000',
  expected: false,
},{
  str: '1_000_',
  expected: false,
},{
  str: '1__000',
  expected: false,
},{
  str: '1000',
  expected: false,
}]

test(reSeparatedLiteral)

function test(re) {
  for (let i = 0; i < data.length; i++) {
    let currentData = data[i]
    let { str, expected } = currentData

    if(re.test(str) === expected) {
      console.log('✅ Test is passed!', str)
    } else {
      console.log('❌ Test is not passed!', str)
    }
  }
}

В данном случае у меня возникло две проблемы:

  1. Как проверять, что число точно имеет разделитель? (Несовсем уверен как работать с аналогом оператор AND в регулярных варжения (я про это: (?=...)(?=...)), но уверен, что эту проблему можно решить используя подобную запись)
  2. Как проверять, что разделитель это только один символ, а не два?

Про первую проблему. Я попытался делать что-то типа такого: /(?=^\d(_{1,1}|\d)+\d$)(?=^[\D]+$)/, но из-за этого, ни первая, ни вторая строка не проходят проверку.

Важное уточнение: нужно использовать исключительно регулярное выражение, то есть использование строковых методов, не вариант.

P.S. такие числа (литералы) по настоящему поддерживаются в JavaScript, то есть вы можете записать миллион в таком виде: 1_000_000, чтобы сделать его (число) более читаемым.

Ответы

▲ 2Принят

Что не так с ^\d(_{1,1}|\d)+\d$? Строка, соответствующая выражения, должна начинаться с цифры, за которой должен следовать один или более повторов цифры или знака подчёркивания, а потом цифра в конце строки. Обратите внимание, что {1,1} можно всегда удалять, ^\d(_{1,1}|\d)+\d$ = ^\d(_|\d)+\d$ = ^\d[_\d]+\d$.

Решение

^\d+(?:_\d+)+$

См. пример регулярного выражения.

Подробности

  • ^ - начало строки
  • \d+ - одна или более цифр
  • (?:_\d+)+ - один и более повторов последовательности из _ и одной и более цифр (из-за того, что требуется одна и более цифр после _, двойной символ подчёркивания в строке невозможен)
  • $ - конец строки.

Пример:

const reSeparatedLiteral = /^\d+(?:_\d+)+$/
const data = [{
  str: '1_000',
  expected: true,
},{
  str: '10_00',
  expected: true,
},{
  str: '1_0_0_0',
  expected: true,
},{
  str: '_1_000',
  expected: false,
},{
  str: '1_000_',
  expected: false,
},{
  str: '1__000',
  expected: false,
},{
  str: '1000',
  expected: false,
}]

test(reSeparatedLiteral)

function test(re) {
  for (let i = 0; i < data.length; i++) {
    let currentData = data[i]
    let { str, expected } = currentData

    if(re.test(str) === expected) {
      console.log('✅ Test is passed!', str)
    } else {
      console.log('❌ Test is not passed!', str)
    }
  }
}