Найти все слова, заключенные в @{{Word}}@ или {{Word}} из строки

#c# #.net #regex

#c# #.net #регулярное выражение

Вопрос:

Я пишу код для извлечения всех слов, заключенных в @{{}}@ и {{}}, до сих пор я искал в Интернете и нашел приведенный ниже код, который работает так, как ожидалось.

 string sampleString = "A @{{Quick}}@ brown @{{fox}}@ jumps @{{over}}@ a lazy {{dog}}.";
List<string> keywordList = new List<string>();
MatchCollection matchedCollection = Regex.Matches(sampleString, @"(@{{(.*?)}}@|{{(.*?)}})");

foreach (Match m in matchedCollection)
{
    keywordList.Add(m.ToString());
}
 

Приведенный выше код работает нормально, он дает мне 4 элемента, перечисленные ниже, и это правильно.

  1. @{{Quick}}@
  2. @{{Fox}}@
  3. @{{Over}}@
  4. {{dog}}

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

 string sampleString = "A @{{Quick}}@ brown @{{fox jumps @{{over}}@ a lazy {{dog}}.";
 

Код с приведенным выше строковым вводом даст мне три элемента в списке.

Текущий результат:

  1. @{{Quick}}@
  2. @{{fox jumps @{{over}}@
  3. {{dog}}

Ожидаемый результат

  1. @{{Quick}}@
  2. @{{over}}@
  3. {{dog}}

Любое предложение по исправлению этого было бы действительно оценено.

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

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

2. В зависимости от определения, @{{fox jumps @{{over}}@ является правильным. Если только под словом «word» вы не подразумеваете S (что-нибудь, кроме пробела) вместо . (любой символ)

3. Я думаю, в вашем примере вы можете заменить точку . на [^{]

4. Привет @xanatos, я заменил . на S , и это сработало. В моем ключевом слове не будет места, так что это сработает.

Ответ №1:

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

 MatchCollection matchedCollection = Regex.Matches(sampleString, @"(@{{(S*?)}}@|{{(S*?)}})");
 

Ответ №2:

Повторение в регулярном выражении кажется излишним, если вы действительно не хотите знать, присутствовали ли @ или нет. Если вы удаляете их, тогда все будет в порядке Regex.Matches(sampleString, @"{{(S*?)}}")

Ответ №3:

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

 (@?)(?<!{){{(?!{)S ?(?<!})}}(?!})1
 

Объяснение

  • (@?) Группа захвата 1, сопоставьте необязательный @
  • (?<!{){{(?!{) Совпадению {{ не предшествует или не следует {
  • S ? Сопоставьте как можно меньше символов без пробелов 1 раз
  • (?<!})}}(?!}) Совпадению }} не предшествует или не следует }
  • 1 Обратная ссылка на то, что записано в группе 1

<a rel=»noreferrer noopener nofollow» href=»https:///regexstorm.net/tester?p=(@?)(?<!{){{(?!{)S+?(?Демонстрация регулярных выражений .NET

Если наличие более 2 фигурных скобок не является проблемой, вы можете опустить поисковые запросы

 (@?){{S ?}}1
 

Демонстрация регулярных выражений .NET

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

1. Действительно хотите знать, как написать правило, способное обрабатывать эту строку A @{{Quick}}@ brown @{{foxjumps@{{over}}@ a lazy {{dog}}. . Я пытаюсь использовать шаблон forward, но не могу этого сделать. Можете ли вы помочь этому? большое спасибо.

2.@MichaelMao Ты имеешь в виду вот так? (@?)(?<!{){{(?!{)(?:(?!{{)S) ?(?<!})}}(?!})1 regex101.com/r/kQh2h8/1

3. Танкуйте. Выглядит великолепно, но слишком сложно для понимания для меня сейчас.

4. Я думаю, что не используйте S и используйте .*? , но исключите @{{ после первого @{{ и перед первым }}@

5. Мое правило (@{{(.*?)(?!@{{)}}@) означает @{{ , что перед a не может быть двух }}@

Ответ №4:

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

 (@)?{{(?:(?!@{{).)*?}}(?(1)@|)
 

Смотрите доказательство.

C # код:

 var matchedCollection = Regex.Matches(sampleString, @"(@)?{{(?:(?!@{{).)*?}}(?(1)@|)", RegexOptions.Singleline);
 

Объяснение

 --------------------------------------------------------------------------------
  (                        group and capture to 1 (optional):
--------------------------------------------------------------------------------
    @                        '@'
--------------------------------------------------------------------------------
  )?                       end of 1
--------------------------------------------------------------------------------
  {{                       '{{'
--------------------------------------------------------------------------------
  (?:                      group, but do not capture (0 or more times
                           (matching the least amount possible)):
--------------------------------------------------------------------------------
    (?!                      look ahead to see if there is not:
--------------------------------------------------------------------------------
      @{{                      '@{{'
--------------------------------------------------------------------------------
    )                        end of look-ahead
--------------------------------------------------------------------------------
    .                        any character (including n
                             with RegexOptions.Singleline)
--------------------------------------------------------------------------------
  )*?                      end of grouping
--------------------------------------------------------------------------------
  }}                       '}}'
--------------------------------------------------------------------------------
  (?(1)                    if back-reference 1 matched, then:
--------------------------------------------------------------------------------
    @                        '@'
--------------------------------------------------------------------------------
   |                        else:
--------------------------------------------------------------------------------
                             succeed
--------------------------------------------------------------------------------
  )                        end of conditional on 1