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

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

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

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

正規表現

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

Q&A

解決済

6回答

1016閲覧

特定の文字列に挟まれているが、その中に特定の文字列を含んでいない正規表現

pegy

総合スコア245

JavaScript

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

正規表現

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

1グッド

3クリップ

投稿2023/12/24 14:28

やりたいこと

下記のような文字列から"なんと"という文字列を取得したいと考えています。

Javascript

1var str = "Aさん 東京にお弁当を持ってBさんに会いに行く。Aさん なんとBさんに会えず"

試したこと

そこで、以下のような正規表現でstr.matchをすると東京にお弁当を持ってを取得してしまいます。

JavaScript

1var pattern = /Aさん (.+?)Bさん/;

なるほど、前段に最短でマッチするものが存在していることに気が付きました。今度はこのマッチしてほしくないケースについては、必ずその間に東京か大阪が含まれる文脈であることがわかっているため、以下のようなパターンを当ててみました。

JavaScript

1var pattern = /Aさん ^(?!東京|大阪)(.+?)Bさん/;

そると期待するなんとは取得できずに何も一致が得られない結果となりました。どのように東京、大阪を含む記載を否定して、なんとを取得できますでしょうか?

SugiuraY👍を押しています

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

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

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

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

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

guest

回答6

0

melianさんの回答だと、「Aさん なんとBさんに会えず。Aさん 東京にお弁当を持ってBさんに会いに行く。」のように順番が逆だとマッチしませんね。
マッチしない理由が分かりにくいですが、(?!の直後の.*?が「なんとBさんに会えず。Aさん 」にマッチしてしまうからでしょう。もうちょと工夫するとなんとかなるのかも知れませんが、下記のように正規表現はシンプルにして、言語側で対応するのが簡明です。複数個あっても対応できます。また、除外条件が複雑になった場合の対応も、判断するコードを追加するだけなので簡単です。

JavaScript

1function test(str){ 2 const pattern = /Aさん(.*?)Bさん/g; 3 const exclude = /東京|大阪/; 4 const match_str = [...str.matchAll(pattern)].map(m => m[1]); 5 const result = match_str.filter(m => !m.match(exclude)); 6 console.log(result); 7} 8 9test("Aさん 東京にお弁当を持ってBさんに会いに行く。Aさん なんとBさんに会えず"); 10// => [ ' なんと' ] 11test("Aさん なんとBさんに会えず。Aさん 東京にお弁当を持ってBさんに会いに行く"); 12// => [ ' なんと' ] 13test("Aさん なんとBさんに会えず。Aさん 東京にお弁当を持ってBさんに会いに行く。AさんやっぱりBさんに会えず"); 14// => [ ' なんと', 'やっぱり' ]

投稿2023/12/24 18:13

編集2023/12/25 00:01
otn

総合スコア85766

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

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

pegy

2023/12/28 04:24

ご返信遅くなり誠に申し訳ございません。まったく想像もできなかったアプローチであったので大変勉強になりました!ありがとうございます。
pegy

2023/12/28 04:25

特に最後のパターンのようなものがあり得ますが、想定の視野に含めていなかったので、とても助かりました。
otn

2023/12/29 09:05

> まったく想像もできなかったアプローチ 「~~を含まない」というのは正規表現は苦手なので、無理矢理やって出来ても複雑になりがちなので、 プログラミング言語で使う場合は、言語側でやるのが簡単です。 プログラミング言語じゃなくてロジックが書けない場所で使うとかはしょうがないですが。 あるいは、何百万回ものループの中で実行するので、言語側でやると律速段階になるとかであればこれも別。
guest

0

遅くなりましたが、先読み後読みを使った解法が無いため

ーーー

/(?<=Aさん) [^東].*(?=Bさん)/
先読み演算子と後読み演算子、そして否定を使えばいけます

イメージ説明

投稿2024/01/16 15:16

kyamad9

総合スコア11

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

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

think49

2024/01/17 12:03

@kyamad9 さん この回答の場合、「マッチしてほしくないケースについては、必ずその間に東京か大阪が含まれる文脈であることがわかっているため」の要件を満たしていないと思います。 /(?<=Aさん) [^東].*(?=Bさん)/.exec("Aさん 大阪にお弁当を持ってBさんに会いに行く。Aさん なんとBさんに会えず") /(?<=Aさん) [^東].*(?=Bさん)/.exec("Aさん Bさんに会いに東京に行く。Aさん なんとBさんに会えず") > 先読み後読みを使った解法が無いため @takanaweb5さんの回答が先読み後読みを使った解法だと思います。 https://teratail.com/questions/bm3aokcozysxuv#reply-aooaq08i1a2xh4 あえて@takanaweb5さんの回答に修正案を出すなら、改行が内在できないのでsフラグを付ける修正でしょうか。
guest

0

javascript

1var pattern = /Aさん ((?:(?!東京|大阪).)+?)Bさん/; 2const match = str.match(pattern); 3console.log(match[1]);

サブマッチの1つ目を取り出します

以下追加情報
参考記事
https://qiita.com/pal4de/items/7e2292cfd7ac424e0836#応用例

強引にサブマッチを使わず、一致文字として取り出したいなら

javascript

1var pattern = /(?<=Aさん )((?!東京|大阪).)+?(?=Bさん)/;

投稿2023/12/25 12:32

編集2023/12/25 23:13
takanaweb5

総合スコア359

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

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

pegy

2023/12/28 04:22

ありがとうございます。正直サブマッチを使わない後段がまだ咀嚼できずにいるのですが、ゆっくり考える時間をいただきたくいったん本件は閉じたいと考えております。ご了承くださいませ。
guest

0

ベストアンサー

文字列全体に特定の文字列が存在しない事を保証するには、1文字ずつ判定させる必要があります。

javascript

1const str = "Aさん 東京にお弁当を持ってBさんに会いに行く。Aさん なんとBさんに会えず" 2const result = /Aさん((?:(?!東京|大阪|Bさん).)*)(?=Bさん)/s.exec(str); 3console.log(result[1]); // "なんと"

Re: pegy さん

投稿2023/12/24 19:09

編集2023/12/26 09:43
think49

総合スコア18189

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

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

pegy

2023/12/28 04:18

遅くなり誠に〆申し訳ございません、おっしゃる方法で解決できました!ありがとうございます〆
guest

0

Windows 11、cscriptコマンドにて確認。match結果の2個目が「なんと」になります。

var pattern = /Aさん ((?!.*(東京|大阪)).*)Bさん/;

think49さんのコメントを受けて、修正しました。

var pattern = /Aさん (((?!Aさん|Bさん|東京|大阪).)*)Bさん/;

投稿2023/12/24 17:18

編集2023/12/24 20:48
hiroki-o

総合スコア1057

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

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

think49

2023/12/24 19:12

”Bさん” の後に "東京" または "大阪" があるとマッチしないですね…。 /Aさん ((?!.*(東京|大阪)).*)Bさん/.exec('Aさん foo Bさん 東京')
pegy

2023/12/28 04:18

遅くなり誠に申し訳ございません、解決に至ることができました!
guest

0

どのように東京、大阪を含む記載を否定して、なんとを取得できますでしょうか

javascript

1const str = "Aさん 東京にお弁当を持ってBさんに会いに行く。Aさん なんとBさんに会えず"; 2const pattern = /Aさん (?!.*?(?:東京|大阪))(.+?)Bさん/; 3const match = str.match(pattern); 4console.log(match[1]) 5 6# なんと

投稿2023/12/24 15:10

melian

総合スコア20574

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

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

pegy

2023/12/28 04:19

お力添えありがとうございます、抽出を確認することができました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問