- - PR -
正規表現
1
投稿者 | 投稿内容 | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2007-01-14 17:22
お世話になっています。
裁判所名が書かれたテキストを扱う機会があったのですが、 次のように支部・出張所が続く場合でも必ず裁判所の後に改行が入っています。 札幌地方裁判所 札幌地方裁判所 室蘭支部 札幌家庭裁判所 札幌家庭裁判所 夕張出張所 これを、 札幌地方裁判所 札幌地方裁判所室蘭支部 札幌家庭裁判所 札幌家庭裁判所夕張出張所 のように各裁判所ごとにまとめる必要があります。 これをコーディングすることは難しくありませんし、 数は多くないので手動で行いましたが、 現在学習中の正規表現ではどのようにやればいいのかと考えています。 「改行・または文頭」から、「次の改行・または文末」の位置まで。 ただし、次の行が「裁判所」で終わっていない改行はマッチを許す と考えて、 Dim text As String = "札幌地方裁判所" & ControlChars.Lf & _ "札幌地方裁判所" & ControlChars.Lf & _ "室蘭支部" & ControlChars.Lf & _ "札幌家庭裁判所" & ControlChars.Lf & _ "札幌家庭裁判所" & ControlChars.Lf & _ "夕張出張所" & ControlChars.Lf & _ "那覇地方裁判所" & ControlChars.Lf & _ "那覇地方裁判所" & ControlChars.Lf & _ "石垣支部" & ControlChars.Lf & _ "石垣簡易裁判所" Dim pattern As String = "" & _ "(?:\n|^) (?#「改行」または「文頭」から)" & _ "(?<name>.+(?=\n.+裁判所.+\n))" & _ "(?=\n|$) (?#「次の改行」または「文末」の直前の位置まで)" For Each m As Match In Regex.Matches(text, pattern, RegexOptions.IgnorePatternWhitespace) MessageBox.Show(m.Groups("name").Value) Next としてみたのですが、うまくいきません。 肯定の先読みを次のように否定の先読みに変えても結果は変わりますがだめです。 Dim pattern As String = "" & _ "(?:\n|^) (?#「改行」または「文頭」から)" & _ "(?<name>.+(?!\n.+裁判所\n))" & _ "(?=\n|$) (?#「次の改行」または「文末」の直前の位置まで)" これを正規表現で解決するにはどうすればいいのか、 ご教授よろしくお願いします。 | ||||||||||||||||||||||||
|
投稿日時: 2007-01-14 18:25
初めに上げた例ではダメですね。
(?<name>.+(?=\n.+裁判所.+\n))の部分は 〜支部や〜出張所には裁判所は含まれていないので、すべて失敗します。 | ||||||||||||||||||||||||
|
投稿日時: 2007-01-14 22:15
\n(?!.*裁判所$)
を削除 EmEditorで動いたけど.netで動くか不明 [ メッセージ編集済み 編集者: 明智重蔵 編集日時 2007-01-14 22:18 ] | ||||||||||||||||||||||||
|
投稿日時: 2007-01-14 23:53
明智さん、ありがとうございます。
全体のパターンは、 "(?:\n|^)(.+)(?=\n|$)" ということでしょうか? EmEditorのフリー版を落としてみたのですが、 これでは行ごとにマッチするだけなので、 違うパターンですか? | ||||||||||||||||||||||||
|
投稿日時: 2007-01-15 19:42
正直、正規表現で片付ける問題じゃあないと思いますが、
こんなところでしょうか?
| ||||||||||||||||||||||||
|
投稿日時: 2007-01-15 21:40
paniponi-xさん、ありがとうございます。
>正直、正規表現で片付ける問題じゃあないと思いますが 私もそう思いますが、ちょうど勉強中だったので ^^;) paniponi-xさんが書いてくださったコードをコピペして試させてもらいましたが、 行単位で出力されるようです。 で、なんとか私も考えまして、 とりあえず出来た気がします。 (もっと処理が高速な書き方がある気がしますが。) Dim text As String = "札幌地方裁判所" & ControlChars.Lf & _ "札幌地方裁判所" & ControlChars.Lf & _ "室蘭支部" & ControlChars.Lf & _ "札幌家庭裁判所" & ControlChars.Lf & _ "札幌家庭裁判所" & ControlChars.Lf & _ "夕張出張所" & ControlChars.Lf & _ "那覇地方裁判所" & ControlChars.Lf & _ "那覇地方裁判所" & ControlChars.Lf & _ "石垣支部" & ControlChars.Lf & _ "石垣簡易裁判所" Dim pattern As String = "" & _ "(?:\n|^)" & _ "[^\n]+(\n((?!裁判所).)+(?=\n))?" For Each m As Match In Regex.Matches(text, pattern, RegexOptions.IgnorePatternWhitespace) MessageBox.Show(m.Value) Next | ||||||||||||||||||||||||
|
投稿日時: 2007-01-16 00:14
すみません。 一度作ったものをさらにコンパクトにしたときにちょっと間違えたようです。
を
にしてください((?: のあとの \\n の位置を修正)。 これで支部や出張所が泣き別れになりません。 スピード云々ですが、まあ対象がそんなに大きくなければそんなに 気にすることはないと思いますが
先読みと単一のキャラクタの読み込みを繰り返すのはオーバーヘッドが 大きくなることが予想されるので、それしか手段がないというのでなければ 避けたほうが無難です。 あとは RegexOptions のプロパティ(でいいんだっけ?)を良く調べてみると 良いと思います。
という記述をすっきりできると思いますよ。 | ||||||||||||||||||||||||
|
投稿日時: 2007-01-16 21:31
できました!
質問した内容だけでなく、RegexOptionの使い方もとても参考になりました。 paniponi-xさん、明智さん、ありがとうございました。 |
1