Как эта замена регулярного выражения перевернуть строку?
Это четвертая часть в серии образовательных регулярных выражений. Это показывает, как сочетается вложенная ссылка (см .:Как это регулярное выражение находит треугольные числа?) «считать» в утверждениях (см .:Как мы можем сопоставить ^ 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