Может быть, мне нужно регулярное выражение?

#c# #regex

Вопрос:

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

 FileSystemWatcher fsw = new FileSystemWatcher(@"c:temp");
fsw.Created  = new FileSystemEventHandler(fsw_Created);

bool monitor = true;

while (monitor)
{
    fsw.WaitForChanged(WatcherChangeTypes.Created, 1000);
    if(Console.KeyAvailable)
    {
        monitor = false;
    }
}

Show("User has quit the process...", ConsoleColor.Yellow);
 

Когда поступают новые файлы, вызывается «WaitForChanges», и тогда я могу приступить к работе.

Что мне нужно сделать, так это проверить имя файла на наличие шаблонов. В реальной жизни я помещаю видеофайлы в эту папку. Основываясь на имени файла, у меня будут правила, которые перемещают файлы в определенные каталоги. Так что на данный момент у меня будет список пар значений ключей… держа регулярное выражение (я думаю?) и папку. Таким образом, если имя файла соответствует регулярному выражению, оно перемещает его в соответствующую папку.

Примером имени файла является:

 CSI- NY.S07E01.The 34th Floor.avi
 

Итак, мое регулярное выражение должно посмотреть на него и посмотреть, существуют ли слова CSI «И» (Нью-Йорк»,» Нью-Йорк «ИЛИ» Нью-Йорк»). Если они это сделают, я затем перенесу их в SeriesCSINY папку.

Мне нужно И, потому что другой пример файла для другой серии:

 CSI- Crime Scene Investigation.S11E16.Turn On, Tune In, Drop Dead
 

Так что для этого мне нужно было бы иметь несколько «Нет». Итак, мне нужно проверить, есть ли в имени файла CSI, но НЕТ («Нью-Йорк», «Нью-Йорк» или «Нью-Йорк»)

Может ли кто-нибудь помочь мне с этими регулярными выражениями? Или, может быть, есть лучший метод?

Ответ №1:

Вы можете попробовать сохранить условия в Func<string,bool>

 Dictionary<Func<string,bool>,string> dic = new Dictionary<Func<string, bool>, string>();
Func<string, bool> f1 = x => x.Contains("CSI") amp;amp; ((x.Contains("NY") || x.Contains("New York"));

dic.Add(f1,"C://CSI/");

foreach (var pair in dic)
{
    if(pair.Key.Invoke("CSI- NY.S07E01.The 34th Floor.avi"))
    {
        // copy
        return;
    }
}
 

Ответ №2:

Я думаю, у вас есть правильная идея. Хорошая особенность этого подхода заключается в том, что вы можете добавлять/удалять/редактировать регулярные выражения в файл конфигурации или какой-либо другой подход, что означает, что вам не нужно перекомпилировать проект каждый раз, когда вы хотите отслеживать новое шоу.

Регулярное выражение для CSI И NY будет выглядеть примерно так. Сначала, если вы хотите проверить, существует ли CSI в имени файла, регулярное выражение просто "CSI" . Имейте в виду, что по умолчанию он чувствителен к регистру. Если вы хотите проверить, существуют ли Нью-Йорк, Нью-Йорк или Нью-Йорк в имени файла, регулярное выражение "((NY)|(New York)|(NewYork))" Столбики указывают ИЛИ, а скобки используются для обозначения групп. Чтобы объединить их, вы можете запустить оба регулярных выражения, и в некоторых случаях (где, возможно, порядок не имеет значения) это может быть проще. Однако, если вы всегда ожидаете, что тип show появится после синтаксиса, будет "(CSI).*((NY)|(New York)|(NewYork))" Точка означает «любой символ», а звездочка означает ноль или более.

Комментарии:

1. Хммм.. На мой взгляд, я действительно не думаю, что регулярное выражение является лучшим вариантом в этом контексте 🙁

2. Возьмите количество, которое соответствует последовательно, я имею в виду, как бы вы выразились str.Contains("A") amp;amp; str.Contains("B") регулярным выражением?

3. @Оскар — я тоже не уверен, что это так. Однако регулярные выражения полезны, и ОПЕРАЦИЯ права, по крайней мере, рассматривая их.

4. Не берите в голову. Я просто говорю, что для того, чтобы сделать что-то такое простое, как «A amp;amp; B», вам нужно будет проверить бота: .*A.*B и .*B.*A.* или что-то в этом роде.

Ответ №3:

Это не выглядит как одно регулярное выражение, даже если вам удастся объединить все это в одно целое. Регексы, которые соответствуют «чему угодно без данного слова», — это боль. Мне лучше придерживаться двух регексов для каждого правила: один, который должен совпадать, и другой, который НЕ должен совпадать для срабатывания этого правила. Если вам нужны ваши «CSI» и «NY», но вам не нравится фиксировать какой-либо определенный порядок в имени файла, вы также можете переключиться с пары регулярных выражений на пару списков регулярных выражений. В общем, лучше вложить эту логику в код и конфигурацию и сохранить регексы как можно более простыми. И да, вам, скорее всего, сойдет с рук простой поиск по подстрокам, нет явной необходимости в регексах, пока вы сохраняете свой код достаточно умным.

Ответ №4:

Ну, люди уже дали вам несколько советов о том, как это сделать с помощью:

  • Регулярные выражения
  • Функция и сохранение именно того кода C#, который будет выполнен в файле

так что я просто дам тебе другой вариант.

Я не согласен с использованием регулярных выражений для этой цели. Я согласен с @Anton S. Kraievoy: мне не нравится, когда регулярные выражения соответствуют чему-либо без данного слова. Это проще проверить: !text.Contains(word)

Второй вариант выглядит идеально, если вы ищете быстрое решение, но…

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

  • Определите, как вы будете хранить эти шаблоны (в классе с членами или в строке и т. Д.). Примером строки может быть:
    • "CSI" amp; ("NY" || "Las Vegas")
  • Затем напишите модуль, который будет соответствовать имени файла с этим шаблоном.

Вы создаете своего рода DSL.

Почему это лучше, чем просто вставить непосредственно код C#?

Ну, потому что:

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

Дело в том, как сопоставить шаблон с именем файла.

У вас есть несколько вариантов:

  • Напишите грамматику вашего шаблона и напишите синтаксический анализатор самостоятельно
  • Сгенерируйте (я не уверен на 100%, что это возможно, это зависит от грамматики) регулярное выражение, которое преобразует вашу грамматику в код C#.
    Например: "A" amp; "B" к string.Contains("A") amp;amp; string.Contains("B") или что-то в этом роде.
  • Используйте для этого инструмент, например ANTLR.

Комментарии:

1. Спасибо Оскару Медеросу — это тоже очень хорошо… Вручную сделать это кажется достаточно простым… Спасибо.