Подтвердить что ты не робот

Регулярное выражение для пропуска символа в группе захвата

Можно ли пропустить пару символов в группе захвата в регулярных выражениях? Я использую регулярные выражения .NET, но это не имеет значения.

В принципе, я ищу:

[случайный текст] AB-123 [случайный текст]

и мне нужно захватить 'AB123', без дефиса.

Я знаю, что AB - это 2 или 3 заглавных буквы, а 123 - 2 или 3 цифры, но это не сложная часть. Жесткая часть (по крайней мере для меня) пропускает дефис.

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

Любые предложения?

4b9b3361

Ответ 1

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

Ответ 2

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

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( "-", "" );

Ответ 3

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

Вы также можете сделать как Джефф-Хиллман и просто вычеркнуть плохих персонажей после этого факта.

Важно отметить здесь, что вы "не используете регулярное выражение для всего".

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" ; 

Ответ 4

Вы можете использовать вложенные группы захвата, например:

((AB)-(123))

Первая группа захвата AB-123, вторая - AB, а третья - 123. Тогда все, что вам нужно сделать, это присоединиться к второй и третьей группе с пробелом.

Ответ 5

Вид поздно, но я думаю, что понял это. По крайней мере, один из способов сделать это.

Я использовал позитивный взгляд, чтобы остановиться на знаке # в тексте. Я не хотел пространства или знака #, поэтому мне нужно было понять, как "пропустить" их. Поэтому, когда я был вынужден снова сопоставить их, я бросил их в группу мусора, которую я не планировал использовать (.ie, немного ведро), которое в коде. Теперь мой указатель места - это одна позиция персонажа за пределами знака # (где я хочу быть, пропуская пробел и знак #). И теперь я просто подошел к концу имени файла в. и игнорировать расширение файла.

(?i)English\\(?<Series>[^ ]+) - (?<Title>.+(?= #))(?<garb1>..)(?<Number>[^.]+)(?-i)

Имя файла, на котором оно было использовано, - это

F:\Downloads\Downloads\500 Comics CCC CBR English\Isukani - Great Girl #01.cbr