Почему это регулярное выражение не принимает ввод типа «s 1»?

0

Я имею следующее регулярное выражение: /([^\s*][\l\u\w\d\s]+) (\d)/ Он должен соответствовать строкам формы: "некоторая строка цифр", например " stackoverflow 1 ". Эти строки не могут иметь пробелов в начале.

Он отлично работает, за исключением простых строк с одним символом в начале, например: "s 1". Как я могу это исправить? Я использую его в boost :: regex (совместим с PCRE).

Теги:

3 ответа

1
Лучший ответ

[^\s*] ест ваш первый строковый символ, поэтому, когда вам понадобится один или несколько строковых символов после него, это не удастся:

/([^\s*][\l\u\w\d\s]+) (\d)/
   ^^^^  ^^^^^^^^^^     ^^
    "s"   no match      "1"

Если вы исправите свое неуместное *:

/([^\s]*[\l\u\w\d\s]+) (\d)/
   ^^^   ^^^^^^^^^^     ^^
   "s";      "s"        "1"
  match
then cancelled
by backtracking

Но чтобы избежать обратного отсчета, я бы вместо этого написал регулярное выражение:

/([\l\u\w\d]+[\l\u\w\d\s]*) (\d)/

Обратите внимание, что я показываю только регулярное выражение - повторно применяйте ваши дополнительные обратные косые черты для использования в строковом литерале C++ по мере необходимости; например

const std::string my_regex = "/([\\l\\u\\w\\d]+[\\l\\u\\w\\d\\s]*) (\\d)/";

В любом случае это может быть сделано более оптимально (я уверен, что большинство этих классов символов избыточны), но это должно устранить вашу непосредственную проблему.

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

  • 1
    Предполагается проверить пробелы в начале строки.
  • 0
    @ REACHUS: Да, я понимаю.
Показать ещё 4 комментария
1

Проблема в том, что у вас есть * в неправильном месте: [^\s*] соответствует точно одному символу, который не является ни пробелом, ни звездочкой. (s в "s 1" квалифицируется как "ни пробелы, ни звездочка", поэтому он сопоставляется и потребляется и больше не доступен для сравнения в следующей части, [\l\u\w\d\s]+. Обратите внимание, что "s 1", с двумя пробелами, будет успешным.)

Вероятно, вы имели в виду [^\s]*, который соответствует любому числу (включая ноль) пробельных символов. Если вы сделаете это небольшое изменение, это исправит ваше регулярное выражение.

Однако есть и другие улучшения. Во-первых, последовательности обратной косой черты, которые являются короткими для классов символов, можно сбрасывать путем заглавной буквы: класс символов "все, что не в \s " может быть записано, как указано выше, с помощью [^\s], но он также может быть написанный более просто как \S

Затем я не знаю, что такое \l и \u. Вы отметили это c++, поэтому вы предположительно используете стандартную библиотеку regex, в которой используется синтаксис регулярных выражений ECMAScript. Но спецификация регулярного выражения ECMAScript не определяет эти метасимволы.

Если вы пытаетесь сопоставить "строчные буквы" и "прописные буквы", это [:lower:] и [:upper:] - но оба набора букв уже включены в \w, поэтому вам не нужно включите их в класс символов, который также имеет \w.

Вытягивание этих элементов оставляет класс символов [\w\d\s] - который по-прежнему избыточен, потому что \w также содержит цифры, поэтому нам не нужно \d. Убрав это, мы имеем [\w\s], который соответствует "подчеркиванию, букве, цифре, пробелу, табуляции, форматированию или переводу строки (новой строке)".

Это делает все регулярное выражение \S*[\s\w]+ (\d): ноль или более символов без пробелов, за которым следует по крайней мере один пробел или символ слова, за которым следует ровно одно пробел, за которым следует цифра. Для меня это кажется необычным набором критериев, но он определенно должен соответствовать "s 1". И это происходит, в моем тестировании.

  • 0
    О да, наверное. Возвращение - это ключ, да.
  • 0
    В общем, движок регулярных выражений будет делать все возможное, чтобы найти совпадение. Если он есть, он его найдет. Все эти правила о самом левом, самом длинном и т. Д. Существуют только для того, чтобы определить, какое совпадение он находит, если их больше одного.
Показать ещё 1 комментарий
-1

Я ожидал, что вы сможете сделать что-то вроде этого:

Добавьте {X,}, где X - число, на второй набор скобок

Как ниже

([^\\s*][\\l\\u\\w\\d\\s]{2,}) (\d)

Замените 2 тем, что вы хотите быть минимальной длиной строки.

  • 0
    Но + уже эквивалентен {1,} , и ОП указал, что он или она хочет, чтобы минимальная длина строки была равна 1. Таким образом, этот ответ, по-видимому, ничего не меняет функционально ...
  • 0
    Это действительно что-нибудь исправит?
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню