理由: プロジェクト内の一部のネットワーク プロトコルに一致させるために正規表現を使用しました。新しいプロトコル A は、表面的には以前の記述形式と同じに見えますが、元の正規表現では依然として A の内容と一致できないため、正規表現の使用と分析を理解するために特別に旅行して、その理由が Windows の改行文字と Linux の改行文字と互換性がないためであることが最終的にわかりました。不慣れな部分なので、私なりの謎解きの過程を記録しておきます。
正規化については、公式の紹介文を直接読んでください:公式の説明
基本的にすべての質問は公式の説明から回答できますが、時間を節約するためです。
以下に、例を使用して、私が遭遇した問題、得られた結論、および使用した方法を説明します。
以下の部分は定期的に一致させる必要がある文字列の構造です / 実際の操作では、同じ文字列内に以下の構造が複数含まれます
// 创建请求 req
struct TestCreateRq {
string Name; // 名称
i32 Icon; // 图标
i32 Type; // 条件类型
i32 requirementParam; // 条件参数
}
次の部分は、私が使用する正規表現です。私がやりたいのは、文字列内の上記の構造をすべて見つけて、構造の説明と構造の名前を出力することです。
//这里是我们使用的匹配规则
Regex reg = new Regex(@"(//.*\r\n)?struct\s*(\w*)\s*{\r\n([\w\W]*?)}\s*", RegexOptions.Multiline);
//这里content是我们用来匹配的字段,里面包含多个上面的结构体
var matches = reg.Matches(content);
foreach (Match item in matches)
{
Debug.Log(item.Result("$1").Replace("//", "").Replace("\r\n", "");
Debug.Log(item.Result("$2"));
}
マッチングルールセクションを直接見てみましょう
正規表現についての質問
質問 1:
文字列の前の @ は何を意味しますか?
回答: @ は C# では必須の非エスケープ記号であり、内部のエスケープ文字は無効です。
例:
Console.WriteLine("你好\t吗?");
//输出结果为:你好 吗?
Console.WriteLine(@"你好\t吗");
//输出结果为:你好\t吗?
質問 2: 正規表現における ( ) は何を意味しますか?
回答:正規表現のグループ構造
質問 3: RegexOptions.Multiline とは何ですか
? 回答:通常の一致ルールの列挙
質問 4:"$1" "$2"
それは何ですか?
回答:正規表現での置換
実際には、上記と以下の組み合わせからわかるはずです。ここで表現されている具体的な内容は、それぞれグループ 1 とグループ 2 に対応する上記 () 内のグループ化の内容ですが、実際の説明は次のとおりです: $number 言語要素には、置換文字列内の数値キャプチャ グループと一致する最後の部分文字列が含まれます。ここで、数値はキャプチャ グループのインデックス
です。たとえば、置換パターン $1 は、一致した部分文字列が最初にキャプチャされたグループに置き換えられることを示します。
したがって、取得する実際のコンテンツは、$1
最初の一致グループ(//.*\r\n)
によって最後に一致した文字列である必要があり、$2
取得するコンテンツは、(\w*)
2 番目の一致グループによって最後に一致した文字列である必要があります。
上記は、よくある質問に対する回答の一部です。
定期的な分析・利用について
使用と分析は実際には同じものであり、ここでの分析は使用のプロセスを逆にしているだけです。ただし、使用する場合でも、逆使用する場合でも、文字の比較が必要です。
上記の解釈に照らして分析を始めましょう
@"(//.*\r\n)?struct\s*(\w*)\s*{\r\n([\w\W]*?)}\s*"
1、@、上記の説明を参照
2、グループ 1 の(//.*\r\n)
分析、この部分の試合の内容は次のとおりです// 创建请求 req
//
一致//
.
「\n」を除く任意の 1 文字に一致します*
直前の部分式の 0 個以上の出現と一致します。\r\n
復帰と一致、改行と一致- 全体的な一致構造は であり
// + 零或多个除“\n”之外的任何单个字符 + 回车换行
、// 创建请求 req
この部分と一致します
3.?
前の 0 個または 1 個の部分式と一致します
。つまり、前の// 创建请求 req
構造は最大 1 個と一致します。一致しない場合でも問題ありません。
4.struct\s*(\w*)\s*
解析すると、この部分の一致する内容は次のとおりです。struct TestCreateRq
struct
一致struct
\s
スペース、タブ、フォーム フィードなどを含む任意の空白文字と一致します。*
直前の部分式の 0 個以上の出現と一致します。(\w*)
グループ 2、式は、\w*
アンダースコアを含む任意の単語文字の 0 個以上の出現と一致します。\s*
スペース、タブ、フォーム フィードなどを含む任意の空白文字と 0 回以上一致します。- 全体的な一致構造は であり
struct + 零次或多次任何空白字符,包括空格、制表符、换页符等 + 零次或多次包括下划线的任何单词字符 +零次或多次任何空白字符,包括空格、制表符、换页符等
、struct TestCreateRq
この部分と一致します
5、{\r\n([\w\W]*?)}\s*
解析、この部分の一致の内容は次のとおりです
{ string Name; // 名称 i32 Icon; // 图标 i32 Type; // 条件类型 i32 requirementParam; // 条件参数 }
{
一致{
\r\n
復帰と一致、改行と一致([\w\W]*?)
可能な限り少ない文字列のグループ 3 ( ) は、アンダースコアを含む任意の単語文字 ( )と単語文字 ( ) ではない文字セット ( ) に?当该字符紧跟在其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式尽可能少的匹配所搜索的字符串
0 回以上 ( ) 一致します。*
\w
\W
[]
}
一致}
\s*
スペース、タブ、フォーム フィードなどを含む任意の空白文字と 0 回以上一致します。- 全体的なマッチング構造
{ + 回车换行 +尽可能少的字符串中匹配零次或多次 包括下划线的任何单词字符和非单词字符的字符集合+ } +零次或多次任何空白字符,包括空格、制表符、换页符等 ,
も、マッチングコンテンツと一致します。
以上が私が使用した正規表現の解析ですが、難しいのは*?
生成された非貪欲マッチングの実行順序を理解することですが、非貪欲マッチングの場合は以下の*?
ルールが最初にマッチします。
逆に言えば、意味しか分からないのです。
と書いてあるので以下のように// 创建请求 req
例を書きましょう
- 初め
//
- 真ん中の4文字も使用可能
.*
- 後ろに1人います
req
- 最後に復帰や改行が入る場合もありますが、
\r\n
グループの場合は()を追加してください。 - 結果としては
(//.*req\r\n)
もちろん一致するのですが、なぜ文章が矛盾してしまうのでしょうか?これは用途の多さに関係します。たとえば、一致させたい場合// 创建请求 res
、// 啦啦啦
または// 啦 // 啦 // 啦
現在の一致方法を使用すると、一致しません。これは実際にはあいまい検索として理解でき、あいまいさの度合いが高いほど汎用性が高くなります。使っていく中で、ニーズに応えながら、できる限り汎用性を高めていくのがベストです。
上の例はその良い例です。さて、私たち自身の質問に戻りましょう。
以下の構造を一致させるために使用すると@"(//.*\r\n)?struct\s*(\w*)\s*{\r\n([\w\W]*?)}\s*"
、一致しません。
struct TestCreateRq {
string Name; // 名称
i32 Icon; // 图标
i32 Type; // 条件类型
i32 requirementParam; // 条件参数
}
/r/n
それを販売しないでください。最終的な結果は、Windowsの改行と Linux/n
の改行が異なるため、提供されたコード形式が一貫していないためです。その結果、コードは同じに見えますが。しかしマッチングすると正常にマッチングしません。
では、どうすれば 2 つの改行文字と互換性を持たせることができるでしょうか? 上記の説明を参照すると、/r/n
判断が行われる場所の判断に適合する必要があります/n
したがって、次のように変更できます
//即在换行符中间增加`\r`和`\n`之间增加`?` 即`\r`最多匹配到一个,没有也无所谓。
Regex reg = new Regex(@"(//.*\r?\n)?struct\s*(\w*)\s*{\r?\n([\w\W]*?)}\s*", RegexOptions.Multiline);
最後に、オンライン検証用正規表現の検証やテストに便利な、上司推奨のオンライン検証用正規表現サイトを掲載します。
以上。