Regex соответствует строке NOT, заключенной в скобки

Мне нужно разобрать текст, где с ключевым словом, если оно не окружено квадратными скобками. Я должен сопоставить ключевое слово с. Кроме того, на обеих сторонах должны быть границы слов.

Вот несколько примеров, где с НЕ является ключевым словом:

  • [с]
  • [with]
  • [sometext с sometext]
  • [sometext with]
  • [с sometext]

Вот несколько примеров, где с ключевым словом IS

  • с
  • ] с
  • привет с
  • привет с миром
  • привет [мир] с приветствием
  • привет [мир] с приветствием [мир]

Кто-нибудь может помочь? Спасибо заранее.

Ответ 1

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

Regex regexObj = new Regex(
    @"(?<!     # Assert that we can't match this before the current position:
     \[        #  An opening bracket
     [^[\]]*   #  followed by any other characters except brackets.
    )          # End of lookbehind.
    \bwith\b   # Match ""with"".
    (?!        # Assert that we can't match this after the current position:
     [^[\]]*   #  Any text except brackets
     \]        #  followed by a closing bracket.
    )          # End of lookahead.", 
    RegexOptions.IgnorePatternWhitespace);
Match matchResults = regexObj.Match(subjectString);
while (matchResults.Success) {
    // matched text: matchResults.Value
    // match start: matchResults.Index
    // match length: matchResults.Length
    matchResults = matchResults.NextMatch();
}

Обратные выражения не останавливаются при разрывах строк; если вы хотите, чтобы каждая строка была оценена отдельно, используйте [^[\]\r\n]* вместо [^[\]]*.

Ответ 2

Хороший вопрос. Я думаю, будет легче найти совпадения, в которых применяется шаблон [with], а затем инвертировать результат.

Вам нужно соответствовать [, а не ], а затем with (а затем соответствующий шаблон для закрытой квадратной скобки)

Соответствие [ и with просты.

\[with

добавить lookahead, чтобы исключить ], а также разрешить любое количество других символов (.*)

\[(?!]).*with

то соответствующая замкнутая квадратная скобка, т.е. обратная сторона с изображением.

\[(?!]).*with.*\](?<1[)

немного больше настроек

\[(?!(.*\].*with)).*with.*\](?<!(with.*\[.*))

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

Ответ 3

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

string s = 
  @"[with0]
  [ with0 ]
  [sometext with0 sometext]
  [sometext with0]
  [with0 sometext]


  with1
  ] with1
  hello with1
  hello with1 world
  hello [ world] with1 hello
  hello [ world] with1 hello [world]";

Regex r = new Regex(@"\[[^][]*\]|(?<KEYWORD>\bwith\d\b)");
foreach (Match m in r.Matches(s))
{
  if (m.Groups["KEYWORD"].Success)
  {
    Console.WriteLine(m.Value);
  }
}

Ответ 4

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