これは、一連の教育正規表現記事の4番目の部分です。ネストされた参照(この正規表現は三角数をどのように見つけるか?)とアサーション内の「カウント」(参照:a ^ nb ^nをJava正規表現と一致させる方法)の組み合わせを使用して文字列を反転する方法を示します。 。プログラムで生成されたパターンは、メタパターンの抽象化を使用します(このJava正規表現はパリンドロームをどのように検出しますか?を参照してください)。シリーズで初めて、これらの手法は、文字列全体の照合ではなく、置換に使用されます。
完全に機能するJavaおよびC#の実装が提供されます。心に強く訴える引用が含まれています。
正規表現を使用して文字列を逆にすることは、決して良い考えとは思えませんでした。また、それが可能かどうか、もしそうなら、どのようにそうしようとするかはすぐにはわかりませんでした。
それはまだ良い考えではありませんが、少なくとも今ではそれが可能であることがわかっています。これを行う1つの方法があります。
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);
}
}
Java (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
モードを有効にします。#
^
および$
は、行の先頭と末尾のアンカーです。?
繰り返し指定子はオプション(つまり、0または1)を示します。たとえば、繰り返しの数量詞として、 (つまり、ゼロ以上の)繰り返しが気が進まない/欲張りでない.*?
ことを示します。*
(…)
グループ化に使用されます。(?:…)
非キャプチャグループです。キャプチャグループは、一致する文字列を保存します。バック/フォワード/ネストされた参照(例\1
)、置換置換(例$2
)などが可能です。(?=…)
ポジティブな先読みです; 与えられたパターンの一致があると断言するのは右に見えます。(?<=…)
ポジティブな後ろ姿です; 左に見えます。