Как эта замена регулярного выражения перевернуть строку?

Это четвертая часть в серии образовательных регулярных выражений. Это показывает, как сочетается вложенная ссылка (см .:Как это регулярное выражение находит треугольные числа?) «считать» в утверждениях (см .:Как мы можем сопоставить ^ n b ^ n с регулярным выражением Java?) может быть использован для обращения строки. Программно сгенерированный шаблон использует абстракции мета-шаблона (см .:Как это регулярное выражение Java обнаруживает палиндромы?). Впервые в серии эти методы используются для замены вместо сопоставления всей строки.

Предоставляются полные рабочие реализации Java и C #. Вдохновляющие цитаты включены.

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

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

C #(также на ideone.com)
using System;
using System.Text.RegularExpressions;

public class TwoDollarReversal {    
public static void Main() {
   string REVERSE = 
      @"(?sx) . grab$2"
         .Replace("grab$2",
            ForEachDotBehind(
               AssertSuffix(@"((.) \1?)")
            )
         );
   Console.WriteLine(
      Regex.Replace(
         @"nietsniE treblA --
         hguone llew ti dnatsrednu t'nod uoy ,ylpmis ti nialpxe t'nac uoy fI",

         REVERSE, "$2"
      )
   );
   // If you can't explain it simply, you don't understand it well enough
   // -- Albert Einstein
}      
// performs an assertion for each dot behind current position
static string ForEachDotBehind(string assertion) {
   return "(?<=(?:.assertion)*)".Replace("assertion", assertion);
}
// asserts that the suffix of the string matches a given pattern
static string AssertSuffix(string pattern) {
   return "(?=.*$(?<=pattern))".Replace("pattern", pattern);
}

}
Джава(также на ideone.com)
class TwoDollarReversal {

public static void main(String[] args) {
   String REVERSE =
      "(?sx) . grab$2"
         .replace("grab$2",
            forEachDotBehind(
               assertSuffix("((.) \\1?)")
            )
         );

   System.out.println(
      "taerG eht rednaxelA --\nyrt lliw ohw mih ot elbissopmi gnihton si erehT"
         .replaceAll(REVERSE, "$2")
   );
   // There is nothing impossible to him who will try
   // -- Alexander the Great"
}

static String forEachDotBehind(String assertion) {
   return "(?<=^(?:.assertion)*?)".replace("assertion", assertion);
}
static String assertSuffix(String pattern) {
   return "(?<=(?=^.*?pattern$).*)".replace("pattern", pattern);
}

}

Как в версиях C #, так и в Java, похоже, используется один и тот же общий алгоритм, с небольшими изменениями только в абстрактных деталях реализации.

Очевидно, что это не самый лучший, самый простой и эффективный способ перевернуть строку, Тем не менее, в интересах изучения регулярных выражений; как осмыслить шаблоны; как двигатель работает, чтобы соответствовать им; как соединить разные части, чтобы построить то, что мы хотим; как сделать это так, чтобы его можно было читать и обслуживать; и просто ради радости от изучения чего-то нового, можем ли мы объяснить, как это работает?

Приложение: шпаргалка!

Это краткое описание основных конструкций регулярных выражений:

(?sx) это встроенный флагмодификаторы. s включает режим «одной линии», позволяяточка соответствоватьЛЮБОЙ персонаж (в том числе строки).x позволяетсвободный интервал режим, в котором неэкранированные пробелы игнорируются (и# можно использовать для комментариев).^ а также$ являются началом и концом строкианкеры.? как спецификатор повторения обозначаетнеобязательный (то есть ноль или один из). В качестве количественного показателя повторения, например,.*? это означает, что* (то есть ноль или более) повторениенеохотный/ Нежадным.(…) используются длягруппировка. (?:…) это группа без захвата. Группа захвата сохраняет строку, которой она соответствует; это позволяет назад / вперед / вложенные ссылки (например,\1), замена замены (например,$2), так далее.(?=…) является положительнымсмотреть вперед; он смотрит вправо, чтобы утверждать, что есть совпадение данного образца.(?<=…) является положительнымсмотреть за; это смотрит налево.Языковые ссылки / дополнительные ресурсыMSDN - Элементы языка регулярных выражений -System.Text.RegularExpressionsУчебные руководства по Java / Основные классы / Регулярные выражения -java.util.regex.Pattern

Ответы на вопрос(1)

Ваш ответ на вопрос