Ответ 1
Вкратце: вы не можете. Совпадение всегда последовательное, даже если оно содержит вещи в качестве утверждений с нулевой шириной, нет способа сопоставить следующий символ, если вы хотите получить его после него.
Можно ли пропустить пару символов в группе захвата в регулярных выражениях? Я использую регулярные выражения .NET, но это не имеет значения.
В принципе, я ищу:
[случайный текст] AB-123 [случайный текст]
и мне нужно захватить 'AB123', без дефиса.
Я знаю, что AB - это 2 или 3 заглавных буквы, а 123 - 2 или 3 цифры, но это не сложная часть. Жесткая часть (по крайней мере для меня) пропускает дефис.
Я предполагаю, что я мог бы захватить как отдельно, так и объединить их в код, но мне жаль, что у меня не было более элегантного, регулярного решения.
Любые предложения?
Вкратце: вы не можете. Совпадение всегда последовательное, даже если оно содержит вещи в качестве утверждений с нулевой шириной, нет способа сопоставить следующий символ, если вы хотите получить его после него.
На самом деле не существует способа создать такое выражение, чтобы согласованный текст отличался от того, что найдено в исходном тексте. Вам нужно будет удалить дефис на отдельном шаге либо путем сопоставления первой и второй частей по отдельности, и объединения двух групп:
match = Regex.Match( text, "([A-B]{2,3})-([0-9]{2,3})" );
matchedText = string.Format( "{0}{1}",
match.Groups.Item(1).Value,
match.Groups.Item(2).Value );
Или удалив дефис на шаге, отдельно от процесса сопоставления:
match = Regex.Match( text, "[A-B]{2,3}-[0-9]{2,3}" );
matchedText = match.Value.Replace( "-", "" );
Ваше утверждение о том, что его невозможно обойтись без подгруппы + конкатенация, является правильным.
Вы также можете сделать как Джефф-Хиллман и просто вычеркнуть плохих персонажей после этого факта.
Важно отметить здесь, что вы "не используете регулярное выражение для всего".
Regex предназначен для менее сложных решений для нетривиальных задач, и вы не должны использовать "о, мы будем использовать регулярное выражение" для всего, и вы не входите в привычку думать, что можете решить проблема в одношаговом регулярном выражении.
Когда существует жизнеспособный тривиальный метод, который работает, во что бы то ни стало, используйте его.
Альтернативная идея, если вам нужно возвратить несколько совпадений в тексте кода, - это поиск regex на основе вашего языка с обратным вызовом, который позволяет передавать любую согласованную/найденную группу в вызов функции, подстановка строки. (Особенно удобно при замене регулярных выражений).
Не уверен, как это работает в .Net, но в php вы бы сделали что-то вроде (не точного кода)
function strip_reverse( $a )
{
$a = preg_replace("/-/", "", $a );
return reverse($a);
}
$b = preg_replace_callback( "/(AB[-]?cde)/" , 'strip_reverse' , "Hello World AB-cde" ;
Вы можете использовать вложенные группы захвата, например:
((AB)-(123))
Первая группа захвата AB-123
, вторая - AB
, а третья - 123
. Тогда все, что вам нужно сделать, это присоединиться к второй и третьей группе с пробелом.
Вид поздно, но я думаю, что понял это. По крайней мере, один из способов сделать это.
Я использовал позитивный взгляд, чтобы остановиться на знаке # в тексте. Я не хотел пространства или знака #, поэтому мне нужно было понять, как "пропустить" их. Поэтому, когда я был вынужден снова сопоставить их, я бросил их в группу мусора, которую я не планировал использовать (.ie, немного ведро), которое в коде. Теперь мой указатель места - это одна позиция персонажа за пределами знака # (где я хочу быть, пропуская пробел и знак #). И теперь я просто подошел к концу имени файла в. и игнорировать расширение файла.
(?i)English\\(?<Series>[^ ]+) - (?<Title>.+(?= #))(?<garb1>..)(?<Number>[^.]+)(?-i)
Имя файла, на котором оно было использовано, - это
F:\Downloads\Downloads\500 Comics CCC CBR English\Isukani - Great Girl #01.cbr