Получите ТОЛЬКО третье совпадение строки, используя REGEX без опции \K (C#)

У меня есть обычная строка, как показано ниже:

xxSTART Here we have the first text in 1234 asdf xxENDxxSTART Here we have the second text 999 fffd xxENDxxSTART Here we have the third text 1234 9985Df xxENDxxSTART Here we have the fourth text 1234 asdf Dert xxEND

Я использую следующий REGEX: ^(?:(.*?)\K(xxSTART)){3}(.*?xxEND), чтобы получить ТОЛЬКО третье совпадение xxSTART Here we have the third text 1234 9985Df xxEND. Это хорошо работает в http://www.regexr.com/v1/, но я прочитал статья, в которой говорится, что опция \K не является опцией в C# (Поддержка \K в регулярном выражении) , а в статье Перевод регулярных выражений Perl в .NET говорится об использовании просмотра назад ((?<=…)) вместо. Но я не могу использовать look-behind ((?<=…)) в моем RegEX, кто-нибудь может мне помочь? пожалуйста!!

У кого-нибудь есть идея, как использовать ((?<=…)) в моем RegEX ^(?:(.*?)\K(xxSTART)){3}(.*?xxEND) для замены опции \K?

С уважением,


person AneEx    schedule 09.04.2014    source источник


Ответы (3)


Здесь вам действительно не нужен просмотр назад, вы можете сопоставить xxSTART и все равно получить 3-ю часть, которую вы хотите получить:

^(?:xxSTART.*?){3}\s*(.*?)xxEND

демонстрация ideone

Но если вы действительно хотите использовать просмотр назад (в случае, если вам не нужны какие-либо группы захвата, что ж, в этом случае вы можете рассмотреть возможность использования просмотра вперед для xxEND), вы должны использовать что-то вроде этого:

(?<=^(?:xxSTART.*?){3}\s*).*?(?=xxEND)

демонстрация ideone

person Jerry    schedule 09.04.2014
comment
Большое спасибо за ответ, Джерри, используя первый ^(?:xxSTART.*?){3}\s*(.*?)xxEND, я получаю первые три вхождения: xxSTART Here we have the first text in 1234 asdf xxENDxxSTART Here we have the second text 999 fffd xxENDxxSTART Here we have the third text 1234 9985Df xxEND и анализируя это с другими (?<=^(?:xxSTART.*?){3}\s*).*?(?=xxEND) - this is a 'reversal' of first REGEX, я получаю последнюю третью совпадение. Я думаю, существует ли способ объединить два регулярных выражения ^(?:xxSTART.*?){3}\s*(.*?)xxEND + (?<=^(?:xxSTART.*?){3}\s*).*?(?=xxEND), чтобы получить ТОЛЬКО третье совпадение ..Here we have the third text 1234 9985.. - person AneEx; 11.04.2014
comment
@AneEx Я тебя не понимаю. Оба регулярных выражения дают Here we have the third text 1234 9985Df , если вы посмотрите на примеры выполнения кода в моем ответе. Как вы используете регулярное выражение? - person Jerry; 11.04.2014
comment
Извини, Джерри, я постараюсь быть яснее. Я загружаю 2 изображения RegexBuddy, представляющие мою «проблему» и анализирующие регулярное выражение ниже. Первое изображение (imagizer.imageshack.us/a/img853/1869/5q0v.png) представляют совпадение ^(?:xxSTART.*?){3}\s*(.*?)xxEND желтым и второго (imagizer.imageshack. us/a/img534/492/k3gt.png) представляют синтаксический анализ (?<=^(?:xxSTART.*?){3}\s*).*?(?=xxEND) желтым цветом. Я могу получить выбор третьего совпадения только в одном матче: D, если это возможно. - person AneEx; 11.04.2014
comment
@AneEx Для первого вы должны выбрать первый захват: изображение и для второй, вы не должны перебирать регулярное выражение. Я до сих пор не понимаю, что вы пытаетесь сделать. Где вы используете регулярное выражение? - person Jerry; 11.04.2014
comment
@AneEx Я сказал вам, что вы не перебираете регулярное выражение, и регулярное выражение будет работать хорошо. Но я думаю, если вы хотите быть таким решительным... Этот будет соответствовать только одному (?<=^(?:xxSTART(?:(?!xxSTART).)*){3}\s*)(?:(?!xxSTART).)*?(?=xxEND) независимо от количества циклов. - person Jerry; 11.04.2014
comment
ХАХАХАХАХАХАХА!!! Джерри, ты учитель регулярных выражений!!! Спасибо, очень хорошо работаете!!! Большое спасибо!! :) Я так счастлив с вашим сообщением! - person AneEx; 11.04.2014
comment
@AneEx Не стесняйтесь принять мой ответ, чтобы ваш вопрос также был помечен как решенный :) - person Jerry; 11.04.2014

Просто используйте это:

^(?:xxSTART.*?xxEND){2}(xxSTART.*?xxEND)

Сначала пропустите первые два блока, а затем захватите третий. Здесь не требуется обратного утверждения.

person Sabuj Hassan    schedule 09.04.2014

Простой способ — не накладывать это ограничение внутри регулярного выражения, а вместо этого выполнять подсчет снаружи:

use strict;
use warnings;

my $data = do {local $/, <DATA>};

my $count = 0;
while ($data =~ /(?<=xxxSTART)(.*?)(?=xxEND)/g) {
    if (++$count == 3) {
        print $1;
        last;
    }
}

__DATA__
xxSTART Here we have the first text in 1234 asdf xxENDxxSTART Here we have the second text 999 fffd xxENDxxSTART Here we have the third text 1234 9985Df xxENDxxSTART Here we have the fourth text 1234 asdf Dert xxEND

выходы:

 Here we have the third text 1234 9985Df
person Miller    schedule 09.04.2014