Как динамически объединить два регулярных выражения?

Можно ли объединить два регулярных выражения? Как будто он должен соответствовать этому регулярному выражению или другому. В идеале исключительно (xor).

Например, я хочу проверить номер телефона на соответствие регулярному выражению номера стационарного телефона и регулярному выражению номера мобильного телефона.

Хотел бы я сделать что-то подобное, но это не работает:

const landlinePhoneRegExp = /(^1300\d{6}$)|(^1800|1900|1902\d{6}$)|(^0[2|3|7|8]{1}[0-9]{8}$)|(^13\d{4}$)|(^04\d{2,3}\d{6}$)/
const mobilePhoneRegExp = /^04[0-9 ]+/
const stripOutDelimiters = regex => etc...

const phoneRegExp = `/${stripOutDelimiters(landlinePhoneRegExp)}|${stripOutDelimiters(mobilePhoneRegExp)}/`,

ОБНОВЛЕНИЕ: я забыл добавить, что использую библиотеку Yup для проверки! Код выглядит так:

const validationSchema = (t, i18n) => Yup.object.shape({
  phone: Yup.string()
    .required(t('formValidationPhoneRequired'))
    .matches(localeRegex[i18n.language].phoneRegExp, t('formValidationPhoneInvalid'))
})

Это объясняет, почему я пытался динамически объединить два регулярных выражения в одно, как в нерабочем примере выше.

Я уже некоторое время просматриваю документы, но, похоже, нет способа сделать это. Может быть, lazy() был бы полезен, но, очевидно, я не могу использовать string.matches() тогда ... если я не сопоставлю (landlineMatch || mobileMatch) с boolean (), но как я могу это сделать?

phone: Yup.lazy((value) => {
  const landlineMatch = value.match(localeRegex[i18n.language].landlinePhoneRegExp)
  const mobileMatch = value.match(localeRegex[i18n.language].mobilePhoneRegExp)

  return Yup.string()
    .required(t('formValidationPhoneRequired'))
    .matches( ??? , t('formValidationPhoneInvalid'))
})

person zok    schedule 03.12.2019    source источник
comment
Намного проще, если вы протестируете каждый по отдельности.   -  person ctwheels    schedule 03.12.2019
comment
OP специально сказал, что они хотели бы объединить их динамически, с Javascript и с логикой XOR, поэтому я не думаю, что кто-то из этих двоих ответит на вопрос.   -  person Andrew    schedule 03.12.2019
comment
@ Эндрю уверен, что да, насколько динамично мы здесь говорим, AI?   -  person ctwheels    schedule 03.12.2019
comment
@ctwheels Dynamic для меня подразумевает, что они хотели бы сделать это программно ... В противном случае этот вопрос не имеет отношения к программированию   -  person Andrew    schedule 03.12.2019
comment
@Andrew, значит, две предоставленные нами ссылки считаются динамическими, потому что они представляют способ выполнить это программно, но для вас они не считаются динамическими? Не уверен, что вы имеете в виду.   -  person ctwheels    schedule 03.12.2019
comment
@Andrew: Поскольку исходные 2 регулярных выражения const, они точно не изменятся. Следовательно, предлагаемое решение достаточно хорошее.   -  person anubhava    schedule 03.12.2019
comment
Вы можете комбинировать эти регулярные выражения динамически, используя ответ, который я дал - вам просто нужно удалить / из существующих регулярных выражений и объединить их с | в соответствии с этим ответом. Вы можете делать это динамически. Верно?   -  person TKoL    schedule 03.12.2019
comment
@TKoL Это работает в основном, но будет просто OR, а не XOR   -  person Andrew    schedule 03.12.2019
comment
Имейте в виду, что (^1800|1900|1902\d{6}$) соответствует строкам, которые начинаются с 1800 с любыми символами после (например, 1800abcg*$ù^pihybncisgf456), или строкам, которые имеют 1900 где-то посередине (например ,abcdef1900xrs654ehrbt84), или строкам, которые заканчиваются на 1902, за которым следуют 6 цифр (например, xyz1234561902123456)   -  person Toto    schedule 03.12.2019
comment
Настоящая проблема сводится к этому ^(?:(04\d{8,9})|(04[0-9 ]+))$. Последнее чередование накладывается на первое. Другими словами, первое - это подмножество последнего. Тогда это не квалифицируется как исключающее или исключающее ИЛИ. Все, что нужно, - это сначала обычное ИЛИ подмножества.   -  person    schedule 03.12.2019
comment
Благодарность за вклад каждого! Регулярное выражение, которое я использовал в примере, выглядит немного забавно и не имеет большого значения. Я думаю, что XOR также не имеет большого значения в моем случае. Я придумал, что делает именно то, что мне нужно: const combineRegex = (r1, r2) => new RegExp(`${new RegExp(r1).source}|${new RegExp(r2).source}`)   -  person zok    schedule 04.12.2019


Ответы (1)


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

Чтобы проверить соответствие строки, просто используйте String.prototype.match() :

landlineMatch = str.match(landlinePhoneRegExp)
mobileMatch = str.match(mobilePhoneRegExp)

Нет ярлыка для логического теста XOR, вам просто нужно использовать комбинацию && и ||, например:

(landlineMatch || mobileMatch) && !(landlineMatch && mobileMatch)
person Andrew    schedule 03.12.2019
comment
Или просто if (!landlineMatch !== !mobileMatch) (xor эквивалентен двум выражениям, оценивающим разные логические значения, одно истинное, а другое ложное) - person IceMetalPunk; 03.12.2019