Regex: Я хочу это И это И это ... в любом порядке

Я даже не уверен, возможно ли это или нет, но вот что я хотел бы.

String: "NS306 FEBRUARY 20078/9/201013B1-9-1Low31 AUGUST 19870"

У меня есть текстовое поле, в котором я набираю параметры поиска, и они разделены пробелом. Из-за этого я хочу вернуть совпадение, если строка1 находится в строке, а затем строка2 находится в строке, ИЛИ строка2 находится в строке, а затем строка1 находится в строке. Мне все равно, в каком порядке расположены строки, но они ВСЕ (будет что-то больше 2) должны быть в строке.

Так, например, в предоставленной строке я бы хотел:

"FEB Low"

или

"Low FEB"

... чтобы вернуться как матч.

Я ' m ДЕЙСТВИТЕЛЬНО новичок в regex, прочитайте только некоторые уроки по здесь , но это было некоторое время назад, и мне нужно сделать это сегодня. В понедельник я начинаю новый проект, который намного важнее и не может быть отвлечен этим вопросом. Есть ли способ сделать это с помощью регулярных выражений, или мне нужно перебирать каждую часть поискового фильтра и переставлять порядок? Любая помощь очень ценится. . Благодаря

UPDATE: или мне нужно перебирать каждую часть поискового фильтра и переставлять порядок? Любая помощь очень ценится. . Благодаря

UPDATE: или мне нужно перебирать каждую часть поискового фильтра и переставлять порядок? Любая помощь очень ценится. . Благодаря

UPDATE: Причина, по которой я не хочу перебирать цикл и ищу наилучшую производительность, заключается в том, что, к сожалению, dataTable, который я использую, вызывает эту функцию при каждом нажатии клавиши, и я не хочу, чтобы она зависала.

UPDATE: Спасибо всем за вашу помощь, это было высоко оценено.

ОБНОВЛЕНИЕ КОДА:

В конечном счете, это то, с чем я столкнулся.

string sSearch = nvc["sSearch"].ToString().Replace(" ", ")(?=.*");
if (sSearch != null && sSearch != "")
{
  Regex r = new Regex("^(?=.*" + sSearch + ").*$", RegexOptions.IgnoreCase);
  _AdminList = _AdminList.Where(
                                       delegate(IPB ipb)
                                       {
                                          //Concatenated all elements of IPB into a string
                                          bool returnValue = r.IsMatch(strTest); //strTest is the concatenated string
                                          return returnValue;
                                    }).ToList();
                                       }
}

Класс IPB содержит X элементов и ни одной таблицы на всем сайте. работаю над тем, чтобы столбцы были в одинаковом порядке. Поэтому мне нужно было искать любой заказ, и я не хотел писать много кода для этого. Здесь были и другие хорошие идеи, но я знаю, что моему боссу действительно нравится Regex (проповедует их), и поэтому я подумал, что было бы лучше, если бы я пошел с этим сейчас. Если по какой-либо причине производительность сайта снизится (интранет-сайт), я попробую другой путь. Спасибо всем.

43
задан XstreamINsanity 25 August 2010 в 15:21
поделиться

6 ответов

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

Это будет выглядеть примерно так:

^(?=.*one)(?=.*two)(?=.*three).*$

Это будет соответствовать строке, содержащей "один", "два", "три", в любом порядке (как показано на rubular.com).

В зависимости от контекста, вы можете захотеть поставить якорь на \A и \Z, и использовать однострочный режим, чтобы точка совпадала со всем.

Это не самое эффективное решение проблемы. Лучшим решением было бы разобрать слова во входных данных и поместить их в эффективное представление множества и т.д.

Похожие вопросы


Более практический пример: проверка пароля

Допустим, мы хотим, чтобы наш пароль:

  • Содержал от 8 до 15 символов
  • Должен содержать заглавную букву
  • Должен содержать строчную букву
  • Должен содержать цифру
  • Должен содержать один из специальных символов

Тогда мы можем написать regex вроде этого:

^(?=.{8,15}$)(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*]).*$
 \__________/\_________/\_________/\_________/\______________/
    length      upper      lower      digit        symbol
100
ответ дан 26 November 2019 в 22:37
поделиться

Я думаю, что на сегодня наиболее целесообразно будет ввести string.Split ('') условия поиска и затем перебрать результаты, подтверждающие, что sourceString. Содержит (searchTerm)

var source = @"NS306 FEBRUARY 20078/9/201013B1-9-1Low31 AUGUST 19870".ToLowerInvariant();
var search = "FEB Low";

var terms = search.Split(' ');

bool all_match = !terms.Any(term => !(source.Contains(term.ToLowerInvariant())));

Обратите внимание, что мы используем Any () для установки короткого замыкания, поэтому, если первое условие не соответствует, мы пропускаем проверку второго, третьего и т. Д.


Это не лучший вариант использования RegEx. Манипуляции со строками, необходимые для того, чтобы взять произвольное количество строк поиска и преобразовать их в шаблон, почти наверняка сводят на нет преимущество в производительности сопоставления шаблона с механизмом RegEx, хотя это может варьироваться в зависимости от того, с чем вы сопоставляете.

В некоторых комментариях вы указали, что хотите избежать цикла, но RegEx не является однопроходным решением. Нетрудно создать ужасно неэффективный поиск, повторяющий и пошаговый по символам, как, например, печально известный катастрофический поиск с возвратом , где очень простое сопоставление требует тысяч шагов, чтобы вернуть false .

3
ответ дан 26 November 2019 в 22:37
поделиться
var text = @"NS306Low FEBRUARY 2FEB0078/9/201013B1-9-1Low31 AUGUST 19870";   
var matches = Regex.Matches(text, @"(FEB)|(Low)");
foreach (Match match in matches)
{
   Console.WriteLine(match.Value);
}

Output:
Low
FEB
FEB
Low

Для начала.

2
ответ дан 26 November 2019 в 22:37
поделиться

Используйте string.Split (). Он вернет массив подстрок, которые повторно разделены указанной строкой / символом. Код будет выглядеть примерно так.

int maximumSize = 100;
string myString = "NS306 ФЕВРАЛЬ 20078/9 / 201013B1-9-1Low31 АВГУСТА 19870";
string [] IndividualString = myString.Split ('', maximumSize);

Для получения дополнительной информации http://msdn.microsoft.com/en-us/library/system.string.split.aspx

Изменить: Если вы действительно хотите использовать регулярные выражения, этот шаблон будет работать. [^] * И вы просто будете использовать Regex.Matches (); Код будет примерно таким:

string myString = "NS306 ФЕВРАЛЬ 20078/9 / 201013B1-9-1Low31 АВГУСТА 19870";
шаблон строки = "[^] *"; Regex rgx = новое регулярное выражение (шаблон);
foreach (Соответствует совпадению в совпадениях (ах))
{
// что-то делаем с match.value
}

0
ответ дан 26 November 2019 в 22:37
поделиться

Вам не нужно проверять каждую перестановку, просто разделите поиск на несколько частей «FEB» и «Low» и убедитесь, что каждая часть совпадает. Это будет намного проще, чем пытаться придумать регулярное выражение, которое соответствовало бы всему за один раз (что, я уверен, теоретически возможно, но, вероятно, не практично в действительности).

0
ответ дан 26 November 2019 в 22:37
поделиться

Почему бы просто не выполнить простую проверку текста, поскольку порядок не имеет значения?

string test = "NS306 FEBRUARY 20078/9/201013B1-9-1Low31 AUGUST 19870";
test = test.ToUpper();
bool match = ((test.IndexOf("FEB") >= 0) && (test.IndexOf("LOW") >= 0));

Это нужно для использования регулярного выражения?

4
ответ дан 26 November 2019 в 22:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: