Нахождение последнего вхождения слова

У меня есть следующая строка:

<SEM>electric</SEM> cu <SEM>hello</SEM> rent <SEM>is<I>love</I>, <PARTITION />mind

Я хочу найти последний стартовый тег "SEM" перед тегом "PARTITION". не конечный тег SEM, а начальный тег. Результат должен быть:

<SEM>is <Im>love</Im>, <PARTITION />

Я пробовал это регулярное выражение:

<SEM>[^<]*<PARTITION[ ]/>

но это работает только в том случае, если заключительные теги "SEM" и "PARTITION" не имеют никаких других тегов между ними. Есть идеи?

6 ответов

Решение

А вот и ваш тупой Регекс!!!

(?=[\s\S]*?\<PARTITION)(?![\s\S]+?\<SEM\>)\<SEM\>

Это означает, что "где-то впереди есть тег PARTITION... но пока впереди нет другого тега SEM... соответствует тегу SEM".

Наслаждайтесь!

Вот это регулярное выражение:

(?=[\s\S]*?\<PARTITION) means "While ahead somewhere is a PARTITION tag"
(?![\s\S]+?\<SEM\>) means "While ahead somewhere is not a SEM tag"
\<SEM\> means "Match a SEM tag"

Используйте String.IndexOf для поиска PARTITION и String.LastIndexOf для поиска SEM?

int partitionIndex = text.IndexOf("<PARTITION");
int emIndex = text.LastIndexOf("<SEM>", partitionIndex);

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

new Regex("...", RegexOptions.RightToLeft);

Решение заключается в следующем, я проверил в http://regexlib.com/RETester.aspx

<\s*SEM\s*>(?!.*</SEM>.*).*<\s*PARTITION\s*/> 

Как вы хотите последний, единственный способ определить, это найти только символы, которые не содержат </SEM>,

Я включил "\s*" на случай, если в <SEM> or <PARTITION/>,

По сути, мы исключаем слово </SEM> с:

(?!.*</SEM>.*)

Немного быстро и грязно, но попробуйте это:

(<SEM>.*?</SEM>.*?)*(<SEM>.*?<PARTITION)

и посмотрите, что находится в C#/. Чистый эквивалент $2

Секрет кроется в лениво-соответствующей конструкции (.*?) --- Я предполагаю / надеюсь, что C# поддерживает это.

Понятно, что решение Jon Skeet будет работать лучше, но вы можете использовать регулярные выражения (например, для упрощения разбиения интересующих вас битов).

(Отказ от ответственности: я сам Perl/Python/Ruby человек...)

Вы пробовали это:

<EM>.*<PARTITION\s*/>

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

Другие вопросы по тегам