Регулярное выражение для соответствия одному из двух шаблонов имен файлов

Я пытаюсь сопоставить имена файлов, используя boost::regex, и у меня есть два вида шаблонов:

  1. XYZsomestring
  2. XYsomestringENDING

Строка somestring может быть любой (>0 символов). Начало имени файла либо XYZ, либо XY. Если это XY , должна быть строка ENDING, которая завершает всю последовательность. Я попытался объединить два регулярных выражения с |, но это не сработало. Это соответствует именам файлов с первым шаблоном:

(XYZ)(.*)

и это соответствует именам файлов со вторым шаблоном:

(XY)(.*)(ENDING)

Но когда я их комбинирую, совпадает только первый шаблон:

((XYZ)(.*))|((XY)(.*)(ENDING))

Все это должно быть нечувствительным к регистру, поэтому я использую boost::regex::icase в конструкторе. Пробовал и без этого icase, тоже не работает).

Какие-либо предложения?


person tzippy    schedule 19.06.2015    source источник
comment
Можете ли вы привести несколько конкретных примеров, которые совпадают и не совпадают? И лучше небольшой код, демонстрирующий проблему, потому что само регулярное выражение кажется правильным.   -  person Petr    schedule 19.06.2015
comment
@tzippy, строка XYZENDING должна совпадать?   -  person    schedule 19.06.2015
comment
Попробуйте ((XY)(.*)(ENDING))|((XYZ)(.*))   -  person Wiktor Stribiżew    schedule 19.06.2015
comment
@stribizhev, нет. В строке XYZ не дает истинного результата. Вероятно, лучше использовать + вместо *   -  person    schedule 19.06.2015


Ответы (1)


Могут быть более простые выражения, но я думаю, что регулярное выражение ^xy(?(?!z).*ending$|.*$) должно это делать:

#include <iostream>
#include <string>
#include <boost/regex.hpp>

bool bmatch(const std::string& x, const std::string& re_) {
  const boost::regex re(re_, boost::regex::icase);
  boost::smatch what;
  return boost::regex_match(x, what, re);
}

int main()
{
  std::string re = "^xy(?(?!z).*ending$|.*$)";
  std::vector<std::string> vx = { "XYZ124f5sf", "xyz12345",
                                  "XY38fsj dfENDING", "xy4 dfhd ending",
                                  "XYZ", "XY345kENDI", "xy56NDING" };
  for (auto i : vx) {
    std::cout << "\nString '" << i;
    if (bmatch(i, re)) {
      std::cout <<
        "' was matched." << std::endl;
     } else {
      std::cout <<
        "' was not matched." << std::endl;
     }
  }

  return 0;
}

Вот демонстрация.

Изменить: Кроме того, я думаю, что регулярное выражение ^xy(z.*|.*ending)$ также должно работать.

person nrussell    schedule 19.06.2015