LoginSignup
knowledge9876
@knowledge9876

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

正規表現のOnigmoなどの非包含オペレータは、以下のような正規表現とは動作が異なるのでしょうか?

非包含オペレータは(?~)ですが、以下の書き方とは正規表現としての動作自体が違うのでしょうか?

例文 行の中に東京を含まない行を全部

^(?!.*(東京.*)).+$

神奈川か、静岡を含まない行全部

^(?!.*(神奈川.*|静岡.*|)).+$

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

0

1Answer

非包含演算子「?~」は「対象を含まない文字列」とマッチします。
一方、「?!」は「否定先読み」と呼ばれるものです。
これは「A(?!B)」と書き、「Bが後ろにつかないA」とマッチします。
そもそも「?=」が「先読み」という正規表現です。
これは「A(?=B)」と書き、「Bが後ろにつくA」とマッチします。

Ruby
p "ここは東京です。今日は晴れです".scan(/(?~東京)/)
#=> ["ここは東", "京です。今日は晴れです", ""]
#「東京」ではない(含まない)文字列でマッチしている。

p "ここは東京です。今日は晴れです".scan(/は(?!東京)/)
#=> ["は"]
#「"東京"が後ろにつかない"は"」とマッチしている。(「今日は」の方)

p "ここは東京です。今日は晴れです".scan(/は(?=東京)/)
#=> ["は"]
#「"東京"が後ろにつく"は"」とマッチしている。(「ここは」の方)

p "ここは東京です。今日は晴れです".scan(/は(?~東京)/)
#=> ["は東", "は晴れです"]
#※これだと「"は"+"東京を含まない文字列"」になってしまう。

例はアスタリスクが消えてしまったものと見受けられますが、
例のように^(?!.*東京).*$と書いた場合、 「"~~東京"から始まらない行」 に なります。

Ruby
p "ここは東京です。今日は晴れです".scan(/^(?!.*東京).*$/)
#=> []
p "ここは京都です。今日は曇りです".scan(/^(?!.*東京).*$/)
#=>["ここは京都です。今日は曇りです"]

非包含演算子を使って書いてみると、^(?~.*東京).*$ですが
「"~~東京"から始まらない行」 ではなく、
「『"~~東京"を含まない文字列』から始まる行」 という意味になります。
否定の仕方が異なるところがポイントになります。

"~~東京"から始まっているので、「?!」だとマッチしませんが、
"ここは"という「"~~東京"を含まない文字列」から始まってしまっているので、「?~」だとマッチしてしまいます。

Ruby
p "ここは東京です。今日は晴れです".scan(/^(?~.*東京).*$/)
#=> ["ここは東京です。今日は晴れです"]
p "ここは京都です。今日は曇りです".scan(/^(?~.*東京).*$/)
#=> ["ここは京都です。今日は曇りです"]
2

Comments

Your answer might help someone💌