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

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

詳細はこちら
JavaScript

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

正規表現

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

Q&A

解決済

4回答

1445閲覧

JavaScript正規表現で「それ以外」という表現を使いたい

Woodwind

総合スコア3

JavaScript

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

正規表現

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

0グッド

1クリップ

投稿2021/01/25 02:12

###前提・該当のソースコード
正規表現で文字列1文字列2が残るコードを実装しました。

js

1var str = '文字列1<iframe width="560" src="http://example/abc" frameborder="0"></iframe>文字列2'; 2// srcがこのurlであるiframeだけを削除する 3var url = "http://example/abc"; 4var obj = new RegExp(`<iframe.*?\ssrc=["']` + url + `["'](.*)?>.*</iframe>`) 5var result = str.replace( obj, '' ); 6console.log(result); // -> '文字列1文字列2'

###求めている結果
しかし上記、すべてのiframeが削除されてしまいますが、最初だけでいいのです。

例えばstrを次に変えて、文字列1文字列2<iframe width="560" src="http://example/abc" frameborder="0"></iframe>文字列3を残したいです。

js

1var str = '文字列1<iframe width="560" src="http://example/abc" frameborder="0"></iframe>文字列2<iframe width="560" src="http://example/abc" frameborder="0"></iframe>文字列3';

###考えた原因と対策
おそらくですが、.*によって、最後の</iframe>まですべてを一致としてしまうのではないかと思っています。
なのでこの部分を下記のように変えてみました。

js

1var obj = new RegExp(`<iframe.*?\ssrc=["']` + url + `["'].*>.*</iframe>`); 2// ↓下記のように変えてみました 3var obj = new RegExp(`<iframe.*?\ssrc=["']` + url + `["'].*>^(?!.*</iframe>)</iframe>`);

^(?!.*</iframe>)</iframe>という文字を含まないを表現したつもりです。
参考:https://uxmilk.jp/50674

しかし何も削除されなくなってしまいました。。
どうすれば求めている結果になるでしょうか?

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

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

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

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

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

guest

回答4

0

ベストアンサー

HTML文字列を正規表現で処理するのはたいてい泥沼にハマります。対応できないパターンが次々と現れたり、可読性が低かったり、応用が難しかったり。もし出力文字列が同値だけど多少変わってもよいのなら、DOM操作したほうが良いです。

javascript

1let str = '文字列1<iframe width="560" src="http://example/abc" frameborder="0"></iframe>文字列2<iframe width="560" src="http://example/abc" frameborder="0"></iframe>文字列3'; 2let url = "http://example/abc"; 3 4let container = document.createElement('div'); 5container.innerHTML = str; 6let iframe = container.querySelector(`iframe[src="${url}"]`); 7if (iframe) 8 iframe.remove(); 9// これが欲しい結果。エスケープが多少変わることあり。 10console.log(container.innerHTML);

投稿2021/01/25 02:30

編集2021/01/25 02:32
int32_t

総合スコア21679

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

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

Woodwind

2021/01/25 02:35

この方法が分かりやすくて好みでした。どうもありがとうございます。今後HTMLに対する正規表現で迷ったらこうします。
Woodwind

2021/01/25 02:42

一点よろしいでしょうか。「エスケープが多少変わることあり」というのはどういう意味になりますか?変わってしまうケースと、例えばどう変わるのか、を教えて頂けませんでしょうか。
int32_t

2021/01/25 05:39 編集

例えば、属性値を囲むシングルクオートがダブルクオートになったり、属性の間のスペースが2つ以上あっても1つになったり、テキスト中の > が &gt; になったり、テキスト中の &#x26; が &amp; になったりします。HTMLとしての意味は変わりません。
Woodwind

2021/01/25 06:02

なるほどです。ありがとうございます。
guest

0

^(?!.*</iframe>)</iframe>という文字を含まないを表現したつもりです。

つもりでしかありません。文字クラス以外に現れた^は、「文字列の先頭」という意味です。

手っ取り早く行うには、.*?として.*を最短一致にしてしまうことかと思います。

投稿2021/01/25 02:18

maisumakun

総合スコア145975

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

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

Woodwind

2021/01/25 02:34

「?」は「直前の文字があってもなくてもいい」だと思っていましたが、「最短一致」という意味になることもあるのすか。難しいですね~。ありがとうございます。
maisumakun

2021/01/25 02:35

上に書いた^もそうですが、正規表現では周囲の状況で意味が変わる文字もあります。
Woodwind

2021/01/25 02:48

みなさんそれをマスターしていらっしゃるわけですね…ガンバリマス
Daregada

2021/01/25 05:18

この使い方の「?」は単独で使うのではなく、「*?」とか「+?」のように直前に特定のメタ文字があります。
guest

0

最初のiframeが合致しない場合2番目を評価する必要があるのかなど
仕様を固める必要があります。

投稿2021/01/25 03:07

yambejp

総合スコア116694

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

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

yambejp

2021/01/25 03:08

それぞれ評価するなら var url = "http://example/abc"; var str = '文字列1<iframe width="560" src="http://example/abc" frameborder="0"></iframe>文字列2<iframe width="561" src="http://example/abc" frameborder="0"></iframe>文字列3'; var tmp=Object.assign(document.createElement('div'),{innerHTML:str}); tmp.querySelectorAll('iframe').forEach(iframe=>{; if(iframe.getAttribute('src')==url){ tmp.removeChild(iframe); } }); str=tmp.innerHTML; console.log(str); ただし、これだとすべて置換してしまうので、仕様にあわせて条件を追加する必要があります
Woodwind

2021/01/25 04:25

たしかに言われてみれば、仕様が定まっていませんでした。もう少し考えます。 しかし前回のご回答もございますので、仕様がなんであれ教えて頂いたコードで対応できそうです。おかげ様で助かりました。 いつもありがとうございます。
guest

0

他の部分は見てませんが、

おそらくですが、.*によって、最後の</iframe>まですべてを一致としてしまうのではないかと思っています。

なのでこの部分を下記のように変えてみました。

.*.*?に変えれば良いだけでは?その前に使っているので機能はご存じですよね?

投稿2021/01/25 02:25

otn

総合スコア85893

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

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

Woodwind

2021/01/25 02:34

「?」は「直前の文字があってもなくてもいい」だと思っていました。。
otn

2021/01/25 02:40

?? では、どんなつもりで、 iframe.*?\ssrc= と書いたのでしょう?
Woodwind

2021/01/25 02:46 編集

どうでもいい説明になってしまうと思いますが。 そこはもともと 「.+?」(何かの文字が1文字以上、それがあってもなくてもいい) と書いていた。 しかし調べると 「.*」(何かの文字が0文字以上) でも同じ意味を表現できると知った。 そこで後者に書き換えようとしたが「?」を除き忘れて「.*?」と質問に記載してしまった。 というかなりどうでもいい経緯でして…不注意でお恥ずかしい限りです。。
otn

2021/01/25 02:50

・そもそも知らなかった ・タイプミスであった ということですね。理解できました。
Daregada

2021/01/25 05:20

「(何かの文字が1文字以上、それがあってもなくてもいい)」という理解が間違っています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問