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

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

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

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

Q&A

解決済

2回答

5539閲覧

正規表現で特定文字で囲まれた文字列を取得したい

gygeai234

総合スコア13

JavaScript

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

1グッド

1クリップ

投稿2018/11/12 16:51

実現したいこと

正規表現を使い、[]で囲んだタグとタグの間を抜き出したいと考えています。

試したこと

下のように、単純に[hoge]~[/hoge]の間であれば実現できているのですが、

let regex = /[([a-zA-Z0-9=-_]+)]([^]]+)[/([a-z]+)]/g const text = "[hoge]Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been[/hoge]" // console.log(text.match(regex)); let myArray; while ((myArray = regex.exec(text)) != null) { console.log(myArray) }

[]のタグが入れ子になっている場合の取得の方法がわかりません。

const text = "[hoge]Lorem Ipsum is simply dummy text of the printing and typesetting [industry]. Lorem Ipsum has been[/hoge]"

下のように、入れ子のタグはバックスラッシュでエスケープし否定先読みで取得が出来るのか、試してみたのですが、うまくいきませんでした。

let regex = /[([a-zA-Z0-9=-_]+)][^(x(?=[)+)][/([a-z]+)]/g const text = "[hoge]Lorem Ipsum is simply dummy text of the printing and typesetting [industry]. Lorem Ipsum has been[/hoge]" // console.log(text.match(regex)); let myArray; while ((myArray = regex.exec(text)) != null) { console.log(myArray) }

良い方法ご存知の方がいましたら、教えていただけないでしょうか。

kaiyu_fish👍を押しています

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

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

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

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

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

guest

回答2

0

[]のタグが入れ子になっている場合の取得の方法がわかりません。

  • [hoge] … 開始タグ
  • [/hoge] … 終了タグ

と用語定義するとして、

  1. 開始タグを検索 (開始タグの数 = 1)
  2. 後続の開始タグor終了タグを検索し、「開始タグの数」「終了タグの数」をカウント
  3. 「開始タグの数 === 終了タグの数」になったら、終了

「開始タグ」「終了タグ」が1文字の場合のコード(アルゴリズムを流用可)。
https://gist.github.com/think49/071350bcc987d82dd836885ea6f5c0d4

Re: gygeai234 さん

投稿2018/11/13 00:05

think49

総合スコア18156

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

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

think49

2018/11/13 03:21

> []のタグが入れ子になっている場合の取得の方法がわかりません。 「入れ子」と書いてあったので、[foo][foo]bar[/foo][/foo] を想定しましたが、[foo][bar]piyo[/bar][/foo] を想定していますか。 もし、そうなら、入れ子ではないのでは…。 /[foo](?:(?![/foo])[^])*[/foo]/g
guest

0

ベストアンサー

こんにちは。

ご質問にある、

正規表現を使い、[]で囲んだタグとタグの間を抜き出したい

という要件をそのまま端的にコードにすると、例えば以下が考えられます。

javascript

1const myArray = text.split(/[/?\w+]/).filter(str => str);

以下は上記を使ったサンプルです。

参考になれば幸いです。

追記

[hoge] ・・・ [/hoge] というテキストの [hoge]タグで囲まれた ・・・ の部分を([industry]も含めて)取り出したいのであれば、以下でどうでしょう?

javascript

1const regexp = /[(\w+)](.+)[/\1]/; 2 3const text = "[hoge]Lorem Ipsum is simply dummy text of the printing and typesetting [industry]. Lorem Ipsum has been[/hoge]"; 4 5const myArray = text.match(regexp); 6 7if (myArray) { 8 console.log(myArray[2]); 9} 10

**上記の動作確認用サンプル: ** https://jsfiddle.net/jun68ykt/h50vnda6/1/

追記

コメント頂きました、以下

ちなみに、[xx]AAA[/xx][xx]BBB[/xx]の様にこのパターンが複数ある場合に、['AAA', 'BBB']の様に結果を取り出したい場合、どの様にするのが良いかご存知でしょうか?

について回答します。以下のように、対象テキストからマッチした部分を削除してループさせていけばできると思います。

javascript

1const regexp = /[(\w+)](.+)[/\1]/; 2 3const contents = []; 4 5let m; 6 7while (m = text.match(regexp)) { 8 contents.push(m[2]); 9 text = text.replace(m[0], ''); 10}

以下は、上記のコードを試すサンプルです。

追記2

"[tag1]AAA[xxx]BBB[/tag1][tag1]CCC DDD[/tag1]EEE[yyy][tag1][yyy]FFFF[/tag1]"

このような文字列の場合には、最初の[tag1]から行末の[/tag1]まですべてマッチしてしまいます。。
こちらについて、何か良い案ございますでしょうか?

についてですが、以下のように (.+)最短マッチ(.+?) に変更すればよいのではと思います。

const regexp = /[(\w+)](.+?)[/\1]/;

以下は上記のサンプルです。

追記3

karamarimoさんからのコメント

karamarimo 2018/11/13 12:24
regex でマッチする部分をすべて見つけたいときは g フラグと regex.exec() を使えば、文字列を削除しなくてもできますよ。

にそって、 regex.exec() を使ってみたものが以下です。

javascript

1const regexp = /[(\w+)](.+?)[/\1]/g; 2 3const contents = []; 4 5let m; 6 7while( m = regexp.exec(text) ) { 8 contents.push(m[2]); 9} 10

上記コードのサンプル: https://jsfiddle.net/jun68ykt/vz76fphe/2/

投稿2018/11/12 21:08

編集2018/11/13 03:38
jun68ykt

総合スコア9058

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

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

gygeai234

2018/11/13 00:58

ありがとうございます! ちなみに、[xx]AAA[/xx][xx]BBB[/xx]の様にこのパターンが複数ある場合に、['AAA', 'BBB']の様に結果を取り出したい場合、どの様にするのが良いかご存知でしょうか? テキスト例: ``` const text = "[hoge]Lorem Ipsum is simply dummy text of the printing and typesetting [industry]. Lorem Ipsum has been[/hoge][hoge]the industry's standard dummy text[/hoge]"; ```
gygeai234

2018/11/13 01:53

ご回答ありがとうございます! 早速試してみました。概ねこれで良さそうです! 度々で申し訳ないのですが、もう一点助言いただけませんでしょうか? 頂いた内容でためしたところ、下の様に "[tag1]AAA[xxx]BBB[/tag1][tag2]CCC DDD[/tag2]EEE[yyy][tag3][yyy]FFFF[/tag3]" タグ名が重複しなければ希望通りの挙動となるのですが、 "[tag1]AAA[xxx]BBB[/tag1][tag1]CCC DDD[/tag1]EEE[yyy][tag1][yyy]FFFF[/tag1]" このような文字列の場合には、最初の[tag1]から行末の[/tag1]まですべてマッチしてしまいます。。 こちらについて、何か良い案ございますでしょうか?
jun68ykt

2018/11/13 02:42

上記について、回答のほうに追記2として返答しました。
jun68ykt

2018/11/13 03:39

@karamarimoさん コメントありがとうございます。ご教示の方法を使ったコードを回答のほうに追記3として記載しました。
gygeai234

2018/11/13 03:47

やりたいことが実現できました。ありがとうございます!
jun68ykt

2018/11/13 04:00

解決されたようで、よかったです ????
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問