#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 элемента, перечисленные ниже, и это правильно.
- @{{Quick}}@
- @{{Fox}}@
- @{{Over}}@
- {{dog}}
Но проблема возникает, когда слово неправильно заключено в скобки / шаблон. Например, если у меня неправильно отформатирована строка, как показано ниже, я получу неверный результат.
string sampleString = "A @{{Quick}}@ brown @{{fox jumps @{{over}}@ a lazy {{dog}}.";
Код с приведенным выше строковым вводом даст мне три элемента в списке.
Текущий результат:
- @{{Quick}}@
- @{{fox jumps @{{over}}@
- {{dog}}
Ожидаемый результат
- @{{Quick}}@
- @{{over}}@
- {{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
Комментарии:
1. Действительно хотите знать, как написать правило, способное обрабатывать эту строку
A @{{Quick}}@ brown @{{foxjumps@{{over}}@ a lazy {{dog}}.
. Я пытаюсь использовать шаблон forward, но не могу этого сделать. Можете ли вы помочь этому? большое спасибо.2.@MichaelMao Ты имеешь в виду вот так?
(@?)(?<!{){{(?!{)(?:(?!{{)S) ?(?<!})}}(?!})1
regex101.com/r/kQh2h8/13. Танкуйте. Выглядит великолепно, но слишком сложно для понимания для меня сейчас.
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