🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
正規表現

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

Q&A

解決済

3回答

2500閲覧

【正規表現】○○で囲まれてない文字列を置換

pipo

総合スコア16

正規表現

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

0グッド

0クリップ

投稿2019/10/07 06:24

お世話になっています。

正規表現で質問です。
掲題の通りですが、特定の文字列に囲まれていない文字列を検索して、置換したいのですが、そのやり方がわからず、
アドバイスいただければと思い質問させていただきます。

やりたいこととしては、

HTML

1<p>hoge<a href="">hoge</a></p>

こんなHTMLに対して、
aタグで囲まれていない"hoge"を"fuga"に置換したいです。

HTML

1<p>hoge<a href="">hoge</a></p> 23<p>fuga<a href="">hoge</a></p>

のような感じです。

よろしくお願いいたします。

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

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

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

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

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

maisumakun

2019/10/07 06:33

たとえば、「<p>hogepiyo<a>hogepiyofuga</a>hoge</p>」のようにあった場合、どこまで置換すればいいでしょうか。
pipo

2019/10/07 06:35

ありがとうございます! <a></a>で囲まれている箇所以外は全て置換したいです
Zuishin

2019/10/07 06:59

<ahoge ahoge="ahoge">ahoge<a href="ahoge">ahoge</a></ahoge> これを置換するとどうなりますか? また言語は何ですか?
pipo

2019/10/07 07:04 編集

ありがとうございます! <ahoge ahoge="ahoge">ahoge<a href="ahoge">ahoge</a></ahoge> の場合だと、 <ahoge ahoge="ahoge">afuga<a href="ahoge">ahoge</a></ahoge> になってもらいたいです 言語はjsで実装予定です
guest

回答3

0

ベストアンサー

出来ない方向でまとまっているようですが、技術的には可能です。

消費する

以下、モバイル端末で未検証コードを書いているので、叩き台にして下さい。

JavaScript

1string.replace(/(<a\s[^>]*>[^<]*(?:<(?!/a>)[^>]*>[^<]*)*</a)(?=>)|(>[^<]*)(?=<|$)/g, (match,anchor,text) => anchor ? anchor : text.replace(/hoge/g, 'fuga'));

ご覧の通り、正規表現が複雑化するので、正規表現に不慣れであれば、お勧めはしません。

先読み

「終了タグが省略されないこと」が保証されているなら、
(上に同じく未検証)

JavaScript

1string.replace(/>([^<]*)(?=(?:<(?!(?:/a>|a[\s>])[^>]*>[^<]*)*(?:<a[\s>]|$))/g, (match,text) => '>' + text.replace(/hoge/g, 'fuga'));

XPath

既存DOMからテキストノード値を書き換えるなら、私はXPathでテキストノードを得て、置換させます。
https://teratail.com/questions/31198

Re: pipo さん

投稿2019/10/07 09:45

編集2019/10/07 23:50
think49

総合スコア18189

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

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

pipo

2019/10/07 10:02 編集

think49さん すごい!! できました!! 僕の知識ではちょっと何をやっているのか理解できませんが、 やっぱり正規表現で対応できるのであれば正規表現でやってしまいたいので参考にさせていただきます!! 本当に助かりました! ありがとうございます!!
guest

0

正規表現は、本質的にHTMLタグのような、ネストしうる構造に対応しきれません(特に、JavaScriptの正規表現は再帰的な拡張もないので難しいです)。

正規表現ではなくDOMで処理したほうがいいのではないかと思います。

投稿2019/10/07 07:14

maisumakun

総合スコア145963

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

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

pipo

2019/10/07 07:22

なるほどです。 正規表現で対応できるところは正規表現でやりたいなーという思いから 色々やってみていましたが、できそーでもできない、、 と時間を喰ってしまっていました。 回答ありがとうございました! jsで実装することにします!
guest

0

自然言語で考える限り、行けそうですが、ちょっと考えてほしいんですけれど、

aaabbbccc

aaaとcccで囲まれている文字列は、bbbということはできますが、

aaaとcccで囲まれて"いない"文字列は、もうね、これ、この文字列そのものにマッチしてしまう。
なんせ、行頭や行末でも、マッチするわけですから。

ほかにも、aaとccで囲まれた文字列も、aaaとcccで囲まれて"いない"なので、abbbcもマッチするでしょう?

というわけで、愚直に実装するのがよろしいかと。
ベン図でイメージしてほしいんですけれど、ある条件で特定の範囲を絞りこむことはできても、
その反転が、必ずしも、限られた条件を示すとは言えない、好例です。

投稿2019/10/07 07:06

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

pipo

2019/10/07 07:19

なるほど、確かにベン図でイメージすると分かりやすいかもしれないですね。 そもそも正規表現の知識が乏しく、できるできないの判断がつかずにいました。 できそうと思って色々試行錯誤していましたが、 はっきりお答えいただいたおかげであまり時間を無駄にせずにすみました! 普通に実装してみます回答ありがとうございました!
think49

2019/10/07 23:28 編集

To: aka-persona さん > aaaとcccで囲まれて"いない"文字列は、もうね、これ、この文字列そのものにマッチしてしまう。 これはどういう意味なのでしょうか。 「囲まれていない文字列」を愚直に実装するなら、「aaaが先行せず、cccが後続しない状態」にします。 後読みが実装を選ぶので、私の回答では<a>を消費してそれを保証しましたが、| を使わず、単体でそれを実装するには前後の文字列チェックが必須です。
think49

2019/10/07 23:54

> 「aaaが先行せず、cccが後続しない状態」にします。 全てにおいて、一対の対応関係が保証されている場合は、上記いずれか一つが成立すれば良かったですね。
退会済みユーザー

退会済みユーザー

2019/10/08 01:09 編集

もう、技術的には解決しているので、全く出る幕はないのですが、"特定の文字列に囲まれていない文字列"というのは、解釈の余地がある表現で、パッと思いつく範囲で ・"特定の文字列"以外の(文字列の開始や終端を含む)何でも囲まれていればOK ・"特定の文字列でないの何らかの文字列"に囲まれていればOK これらのどちらかが不定です。 私の知りうる限り、正規表現エンジンは基本的に最大一致するはずですから、[^(aaa.*ccc)]に対して、aaabbbcccを評価してしまうと、文字列の開始や、文字列の終了は、aaaでもcccでもないので、マッチしてしまうように思えます(間違っていたらすいません)。 翻って、現実的な実装では、think49さんのように、後者の、文脈に応じた実装をする必要があるということが、整理したかったわけです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問