MozillaZine.jp フォーラム
https://forums.mozillazine.jp/

JavaScript /\d*/ が最短マッチ
https://forums.mozillazine.jp/viewtopic.php?f=30&t=14464
ページ 11

作成者:  zxcv [ 2013年12月06日(金) 12:55 ]
記事の件名:  JavaScript /\d*/ が最短マッチ

alert('s123'.match(/\d*/));

を含むHTMLを Firefox25.0.1 で実行すると、空文字列がalertされます。

最長マッチの 123 が正しいと思うのですが、私のFirefoxだけこういう動作をするのでしょうか?

作成者:  バッキー [ 2013年12月09日(月) 23:24 ]
記事の件名:  Re: JavaScript /\d*/ が最短マッチ

Firefox 25.0.1で試してみましたが正規表現のバグっぽいですね。

s\d*だと s123 が返ってきますが \d* だと空文字が返ってきます。
でと、\d\d*だと 123が返ってきました。

'sos123'で同じことを試してみると、
s\d*だと s, \d*だと空文字, s\d\d*だと s123が返ってきました。

検索対象の文字列によって s\d*の結果が変わってしまうのがちょっと謎ですが、とりあえず思惑通りに動かないので えっ? って感じですね。

作成者:  バッキー [ 2013年12月09日(月) 23:28 ]
記事の件名:  Re: JavaScript /\d*/ が最短マッチ

追加情報です。

\d+だと 123が返ってきました。

作成者:  zxcv [ 2013年12月10日(火) 20:54 ]
記事の件名:  Re: JavaScript /\d*/ が最短マッチ

追試ありがというございます。

やはりバグですかぁ・・・
しょっちゅう起こるバグなら大騒ぎになってる筈だと思ったのですが、意外に影響が少ないのでしょうかね。

私はエレメントの id から内部的な管理番号を抽出する処理がうまく動かず、かなり悩みました。
早く直って欲しいです。

作成者:  バッキー [ 2013年12月10日(火) 21:44 ]
記事の件名:  Re: JavaScript /\d*/ が最短マッチ

もしかするとバグは私の勘違いかもしれません。

いままで \d* を単独で使用してこなかったので特に意識していませんでしたが、*は0 回以上の繰り返しにマッチするので 's123'.match(/\d*/)で 空文字が返ってくるのは正常な動作のような気がしてきました。

\d* ではなくて \d+ では正常に 123 が返ってきますので、\d+を使用なさってください。

作成者:  zxcv [ 2013年12月11日(水) 09:12 ]
記事の件名:  Re: JavaScript /\d*/ が最短マッチ

バッキー さんが書きました:
*は0 回以上の繰り返しにマッチするので 's123'.match(/\d*/)で 空文字が返ってくるのは正常な動作のような気がしてきました。

Perlの場合だと、空文字列が帰るならバグですね。
なぜかと言うと \d* の * は最長マッチと決められているからです。

JavaScriptの場合、標準でどう決められているか見付からなかったので自信が無かったのですが、最短マッチするか最長マッチするか予測困難では使えないですし、そもそもそんなのが標準にはならないはずですよね?

作成者:  バッキー [ 2013年12月11日(水) 16:05 ]
記事の件名:  Re: JavaScript /\d*/ が最短マッチ

おっしゃるとおり、確かに * は最長マッチなのですが、IE, Safari, Chromeのどれも 's123'.match(/\d*/)で 空文字が返ってくるんですよ。
この現象が Firefoxだけならバグだとはっきり言えるのですが、他のブラウザと同じ動作なので Javascriptの正規表現ではこれが仕様なのかもしれません。

それにしても不思議なのは 's123'.match(/\d/) は 1が返ってくるんですよね。
だったら \d* で 123が返ってきてもよさそうなものなのですが、、、

作成者:  バッキー [ 2013年12月12日(木) 10:17 ]
記事の件名:  Re: JavaScript /\d*/ が最短マッチ

再確認してみました。
's123'.match(/\d*/)で 空文字が返ってくるのは仕様どおりで正常な動作でした。

zxcv さんが書きました:
バッキー さんが書きました:
*は0 回以上の繰り返しにマッチするので 's123'.match(/\d*/)で 空文字が返ってくるのは正常な動作のような気がしてきました。

Perlの場合だと、空文字列が帰るならバグですね。
なぜかと言うと \d* の * は最長マッチと決められているからです。

\d*は 0文字以上の最長マッチなので \d*を単独で使用した場合、先頭のアルファベットを調べた段階で「0文字以上の数字」という条件が成立するので空文字が返ります。

ということで Perlで空文字が返らないならバグか、別途追加された Perlの正規表現の仕様でしょう。

作成者:  zxcv [ 2013年12月13日(金) 09:56 ]
記事の件名:  Re: JavaScript /\d*/ が最短マッチ

バッキー さんが書きました:
\d*は 0文字以上の最長マッチなので \d*を単独で使用した場合、先頭のアルファベットを調べた段階で「0文字以上の数字」という条件が成立するので空文字が返ります。

「最長マッチ」という用語を理解されていない様ですね。

's123'.match(/\d*/) に対して "123" が最長マッチ、""が最短マッチです。
「最長マッチ」や「最長一致」という語が、世間でどう使われているか確認された方が良いですよ。

せっかくweb標準に移動して頂いたのですから、JavaScriptの仕様という観点でのご意見を希望します。

作成者:  バッキー [ 2013年12月13日(金) 12:12 ]
記事の件名:  Re: JavaScript /\d*/ が最短マッチ

zxcv さんが書きました:
せっかくweb標準に移動して頂いたのですから、JavaScriptの仕様という観点でのご意見を希望します。

では、まず zxcvさん御自身が Javascriptの正規表現の仕様について確認なさってください。
その上で、's123'.match(/\d*/)で空文字が返ってくるのが仕様どおりなのかそうでないのか考えてみてください。

作成者:  通行人 [ 2013年12月24日(火) 13:54 ]
記事の件名:  Re: JavaScript /\d*/ が最短マッチ

zxcv さんが書きました:
Perlの場合だと、空文字列が帰るならバグですね。
なぜかと言うと \d* の * は最長マッチと決められているからです。

JavaScriptの場合、標準でどう決められているか見付からなかったので自信が無かったのですが、最短マッチするか最長マッチするか予測困難では使えないですし、そもそもそんなのが標準にはならないはずですよね?

JavaScriptはPerlではない。
JavaScriptはECMAScriptをベースにしているので、ECMAScriptの仕様書に聞くしかない。
String.matchを見ると、String.match(...)において、... がRegExpオブジェクトでなかったら ... をRegExpオブジェクトに変換し、RegExp.exec()を呼ぶ、云々と書いてある。
そして、RegExp.global=falseで、zero or more occurrencesの時は、長さをゼロにしてRegExp.exec()を一回だけCallし、結果はゼロか正の無限大、となにやら怪しげなことが書いてある。
で、「JavaScriptのRegExpオブジェクト」を見ると、
Metacharacter \d Find a digit
Quantifier n* Matches any string that contains zero or more occurrences of n
Quantifier n+ Matches any string that contains at least one n
Modifier g Perform a global match (find all matches rather than stopping after the first match)
RegExp Object Property global Specifies if the "g" modifier is set

「zero or more occurrences」、「at least one」、および、「global match(対は、non-global matchになるのかな)」、「find all matches rather than stopping after the first match」だからその対は「stopping after the first match」、と定義されている。
Modifier gは、RegExp.globalに対応し、ここでECMAScriptの記述に遭遇。

ここには、最短マッチだの最長マッチだのとは、書かれてはいない。
ましてや、Quantifierの「*」には、最短だの最長だのといった意味合いに対応するものは一切含まれていない。
そういう類のものは、RegExp.globalに分離してある。
(この辺が、仕様書で「intentionally generic」と言っている部分の一つかな)
"\d*"は、「Find a digit」で「zero or more occurrences」で、"/g"が無いから、そのままではglobal=falseで、「stopping after the first match」になる。
「zero or more occurrences」の時にまだ一回もマッチしていないのに「First」 matchとはこれ如何、Firstは1からじゃないのかぃ、ってなチャチャは無し。
イギリスのFirst FloorとアメリカのFirst Floorの違い、ってなことになるのかも。

ま、単に、マニュアルをちゃんと読まないからそうなる、という話になるでしょう。

"/i"ならまだしも、Regular expressionの文字列の中に"/g"を入れるのはちょっと気色悪いから、
var Str=" ... " ; var RegExpForDigit= new RegExp("/\d*/" );
RegExpForDigit.global=false; var a=Str(RegExpForDigit);
RegExpForDigit.global=true; var b=Str(RegExpForDigit);
とでもしてみるといいでしょう。

なお、JavaScriptには拡張が入っているので、ECMAScriptとは異なるものも多々あります。
基本的なものはECMAScriptの厳密な規定にほぼ従っていますが、RegExpでも、少し拡張が入っていたと思います。
何も調べずに、Perlと違う、ECMAScriptと違う、MSと違う、などと言って、bugzilla.mozilla.orgにバグを開かないでくださいね。

ページ 11 All times are UTC + 9 hours
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/