Сложный запрос регулярного выражения PG

У меня есть следующая рабочая функция, которая используется в контрольном ограничении (я опубликую только соответствующую часть SQL):

  -- a comma should always be followed by a space
  -- a period should always be followed by a space, except if it is the last character of the string OR the string contains 'caporal'
  -- a question mark should always be followed by a space, except if it is the last character of the string
  -- must not contain 2 or more spaces in a row
  -- must not contain ((
  -- must not contain ))
  -- any open parenthesis should be closed: number of '(' should equal to number of ')'
  SELECT
    ($1 !~ ',(?!\s)|\s{2}|[?](?!\s(?!$)|$)|[()]{2,}') AND
    ((array_length(string_to_array($1, '('), 1) - 1) = (array_length(string_to_array($1, ')'), 1) - 1)) AND
    ($1 ~ 'caporal' OR $1 !~ '[.](?!\s(?!$)|$)')

Со временем я понял, что мне нужно разрешить период без следующего места для дел:

  • .fr
  • .com
  • .net
  • .co.uk

Кроме того, я понял, что мне нужно разрешить запись чисел с плавающей запятой с запятой/точкой в ​​качестве разделителя. Должны быть допустимы следующие случаи:

  • 2,5cm
  • 10.4l

Я пробовал несколько вещей, но, похоже, я просто нарушаю существующие правила, а не добавляю к ним «исключения».

Моя последняя попытка заключалась в следующем:

  SELECT
    ($1 !~ '[[a-zA-Z]àâçéèêëîïôûùüÿæœ],(?!\s)|\s{2}|[?](?!\s(?!$)|$)|[()]{2,}') AND
    ((array_length(string_to_array($1, '('), 1) - 1) = (array_length(string_to_array($1, ')'), 1) - 1)) AND
    ($1 ~ 'caporal' OR $1 !~ '[[a-zA-Z]àâçéèêëîïôûùüÿæœ][.](?!\s(?!$)|(?!fr)|(?!com)|$)')

Но это явно не то, что я хочу. Заранее спасибо за подсказки и советы!

Попробуйте изменить первое регулярное выражение на ,(?!\d(?<=\d,\d)|\s)|\s{2}|\?(?!\s(?!$)|$)|[()]{2,}, а последнее на \.(?!\d(?<=\d\.\d)|(?:fr|com|co\.uk|(?<=\yco\.)uk|net)\y|\s(‌​?!$)|$). Это должно сделать работу.

Wiktor Stribiżew 21.12.2020 21:29
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
1
68
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы должны изменить первое регулярное выражение на

,(?!\d(?<=\d,\d)|\s)|\s{2}|\?(?!\s(?!$)|$)|[()]{2,}

и последний, чтобы

\.(?!\d(?<=\d\.\d)|(?:fr|com|co\.uk|(?<=\yco\.)uk|net)\y|\s(?!$)|$)

Изменения являются дополнениями к отрицательным прогнозам, которые не находят соответствия, если их шаблоны совпадают непосредственно справа от текущего местоположения.

В первом случае ,(?!\d(?<=\d,\d)|\s) используется для соответствия любой запятой, за которой не следует пробел, или любой цифре, которая является дробной цифрой (поскольку ей должна предшествовать цифра и запятая).

Во втором регулярном выражении добавляется аналогичное ограничение, см. \d(?<=\d\.\d), которое заставляет \. соответствовать точке, которая не является первой дробной цифрой в числе с плавающей запятой с точкой в ​​качестве десятичного разделителя, а часть (?:fr|com|co\.uk|(?<=\yco\.)uk|net)\y добавляется, чтобы избежать совпадения с . за которым следуют fr, com, co.uk, вторая точка в co.uk ((?<=\yco\.)uk просмотр назад гарантирует, что запятая перед uk, которой не предшествует co., все еще совпадает) или net как целые слова (см. \y, граница слова).

Другие вопросы по теме