質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

VBScript

VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Q&A

解決済

3回答

9559閲覧

正規表現で入れ子になっている会話文を抜き出す

hatena19

総合スコア33699

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

VBScript

VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

0グッド

0クリップ

投稿2017/05/12 09:45

編集2017/05/14 04:12

あるテキストから"「"~"」"に挟まれた会話文を抜き出す場合、
正規表現では下記のコードでできました。

Sub RegExpTest() Dim re As VBScript_RegExp_55.RegExp Dim mc As VBScript_RegExp_55.MatchCollection Dim m As VBScript_RegExp_55.Match Dim Data As String Data = "「ABCDEFG1」" & vbCrLf & _ "「abcd" & vbCrLf & _ "efg1」" & vbCrLf & _ "aaa「ABCDEFG2」" & vbCrLf & _ "bbb「abcd" & vbCrLf & _ "efg2b」ccc" Set re = New RegExp re.Global = True re.MultiLine = True re.Pattern = "「((.|\r\n)*?)」" Set mc = re.Execute(Data) For Each m In mc Debug.Print "■"; m.Value; "■" Next End Sub

下記のように"「"~"」"が入れ子になっている場合、
うまく抜き出せません。

Data = "「ABC「DEF」G1」" & vbCrLf & _ "「abc「d" & vbCrLf & _ "ef」g1」" & vbCrLf & _ "aaa「ABCDEFG2」" & vbCrLf & _ "bbb「abcd" & vbCrLf & _ "efg2b」ccc" ```上記の場合、 > ■「ABC「DEF」■ > ■「abc「d > ef」■ > ■「ABCDEFG2」■ > ■「abcd > efg2b」■ というようになってしまいます。 下記のように入れ子部分も含めて抜き出すことは正規表現で可能でしょうか。 > ■「ABC「DEF」G1」■ > ■「abc「d > ef」g1」■ > ■「ABCDEFG2」■ > ■「abcd > efg2b」■ 正規表現を使わずに、VBAのみでループさせて抜き出すことはできています。 正規表現だけで、あるいはVBAとうまく組み合わせて簡単にできないかなと思ったので質問させていただきました。 コードはVBAの例ですが、VBScript や JavaScript でもOKです。 追記 --- 皆さん、回答ありがとうございました。 2階層までというように制限があれば正規表現一発でできるというのは皆様の回答で分かりました。 質問のサンプルは2階層まででしたが、できれば階層制限なしが希望でした。 質問内容が曖昧でした。 標準の正規表現では「無制限の入れ子は表現できない」、 しかし、言語によっては拡張されて可能である。 ということも分かりました。 今回の場合は、正規表現を使わずに、VBAのみで階層制限なしのロジックは完成しているのですが、 正規表現一発でできないのかな、あるいは正規表現を使ってもう少しシンプルに記述できないかなと、疑問の思ったのが質問に至った経緯です。 皆さんの回答は、それぞれみな参考になりましたので、どれをベストアンサーにするのか迷いましたが、 有用なロジックと、実際に使える汎用性の高いコードを提示していただいた、think49 さんとさせていただきました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

これは情報科学の話になってくるのですが、「正規表現」という言葉自体が実は「入れ子は表現できない」という意味を含んでいるのです…

ただ、PerlやRuby、Pythonだと正規表現を鬼拡張した結果入れ子を表現できるようになってしまっており、つまりこれは実は正規表現と呼ぶべきではない代物であったりするのですが、ここら辺のスクリプト言語を使うことをご検討いただければ。

投稿2017/05/12 11:22

yuba

総合スコア5568

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

括弧が2階層までの場合

既に指摘されていますが、2階層までなら正規表現で一度にマッチさせる事が可能です。

JavaScript

1var string = ['「a」', '「「b」」','「「c」「d」」'].join(); 2console.log(string.match(/「(?:[^「」]*「[^「」]*」)*[^「」]*」/g)); // ["「a」", "「「b」」", "「「c」「d」」"]

3階層以上の括弧にマッチさせるには

3階層以上の括弧に対応する為には開始文字()の数と終了文字()の回数が一致するまで再帰的にマッチさせる必要があります。
RegExp#exec で再帰的にマッチさせれば可能です。
が、注意点として 「「「a」 のように対応する括弧で閉じられていないパターンの為にバックトラック処理(マッチに失敗した場合に失敗前の場所まで戻ってマッチをやり直す)が必要になります。

  1. 「「「a」 でマッチ失敗
  2. 「「a」 でマッチ失敗
  3. 「a」 でマッチ成功

ちなみに、2文字以上の文字列を受け付ける汎用性を持たせれば、対応するHTMLタグにマッチさせる事も可能です。

サンプルコード

GitHubにサンプルコードをUPしました。
質問の要件は満たせていると思います。

JavaScript

1var string; 2 3/** 4 * 「xxx」 5 */ 6string = '「「「a」, 「「b」」, 「「c」「d」」, 「「「e」「f」」」, 「「「g」」「「h」」」'; 7console.log(JSON.stringify(findCorrespondingFromString(string, '「', '」'))); // ["「a」","「「b」」","「「c」「d」」","「「「e」「f」」」","「「「g」」「「h」」」"] 8 9/** 10 * <<xxx>> 11 */ 12string = '<<a>>,<<<<b>>>>,<<<<c>><<d>>>>'; 13console.log(JSON.stringify(findCorrespondingFromString(string, '<<', '>>'))); // ["<<a>>","<<<<b>>>>","<<<<c>><<d>>>>"] 14 15/** 16 * <div>xxx</div> 17 */ 18string = `<div id="parent"> 19 <p>text</p> 20 <div class="child"> 21 <p>text</p> 22 <p>text</p> 23 <div class="grandson"> 24 <p>text</p> 25 </div> 26 <div class="grandson">grandson2</div> 27 </div> 28 <div class="child">child2</div> 29</div>`; 30console.log(JSON.stringify(findCorrespondingFromString(string, '<div(?:\\s[^>]*)?>', '</div>'))); // [<div id="parent">...</div>]

更新履歴

  • 2017/05/13 02:13 [サンプルコード] の節を追記。
  • 2017/05/13 08:04 サンプルコードを追記。

Re: hatena19 さん

投稿2017/05/12 12:23

編集2017/05/12 23:04
think49

総合スコア18162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

単に二重の入れ子まででよいなら条件を列記すればいいでしょう

「[^「]?」|「.?「[^「]?」.

投稿2017/05/12 11:36

yambejp

総合スコア114775

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問