/ 最近 .rdf 追記 編集 設定 本棚

脳log[20100531] requireEnd(), hitEnd()



2010年05月31日 (月)

最終更新: 2010-07-10T01:01+0900

[正規表現] requireEnd(), hitEnd()

hitEnd

public boolean hitEnd()

このマッチャーが行なった最前のマッチング操作によって、入力シーケンスの終わりに達していたら、trueを返します。

このメソッドがtrueを返したときは、さらに新たな入力を加えると最後のマッチの結果が変わる可能性があります。

requireEnd

public boolean requireEnd()

入力を新たに増やすことによって、それまでのマッチが不成功に変わるならtrueを返します。

マッチが見つかっていたときにこのメソッドがtrueを返したら、さら入力を増やすとそのマッチがなくなることを意味します。マッチが見つかっていたときにこのメソッドがfalseを返したら、さらに入力を増やすとマッチが変わるかもしれないが、マッチがなくなることはないことを意味します。マッチが見つかっていないときにrequireEndを呼ぶことは、無意味です。

まず 1.5 で導入された hitEnd メソッドと requireEnd メソッドですが、 hitEnd メソッドはドキュメントでは入力の末尾がヒットした場合にtrueを返すとありますが、入力というのは領域を指しているようなのですが、末尾というのが最後の文字なのか末尾の位置なのかよく分かりませんでした。例えば aa をマッチング対象の入力シーケンスとして正規表現 aa でマッチングを行った場合、入力シーケンス全体にマッチしますが、この場合に hitEnd は false を返します。つまり最後の文字がマッチしていても true にはならないようです。ところが正規表現 a+ や a* でマッチングを行うと aa と同様に入力シーケンス全体にマッチしますが、この場合は hitEnd は true となります。つまりマッチした部分だけでなく正規表現パターン自体も hitEnd の返す値に影響するようです。

どちらも入力が一つの文字列におさまっていないときに役に立つメソッド。

  1. 二番目の引用内容と、
  2. requireEnd()が trueを返した場合と hitEnd()が trueを返した場合の対比と、
  3. 自分が行文字列のリストを対象に鬼車でマッチングを行うときに欲しい機能から、

hitEnd()について想像するなら、

search engineが遷移先を残したまま入力を消費し尽くしたときに hitEnd()が trueになる。それの意味することは、直前のマッチが成功していたのなら、さらなる入力によりマッチの範囲が延長される可能性があるということ。直前のマッチが失敗していたのなら、さらなる入力によりマッチが成功するかもしれないということ。

ところで、hitEnd()が trueかつ requireEnd()が trueの場合って存在するだろうか。あるとして、どんな入力とパターンになるだろう。

requireEnd()はなくても困りはしない。マッチの範囲が入力の末尾まで続いていれば無条件に入力を増やしてリトライすることで requireEnd()が trueだったのか falseだったのかは確かめられる。

hitEnd()も、マッチが成功していたときは重要ではない。真価は、マッチが不成功だったときに hitEnd()が falseを返した場合は、さらなる入力をつなげてもマッチが成功に変わることがないと確かにいえること。hitEnd()がなければすべての入力を連結せずにはマッチが存在しないことを断定できない。


そうそうこれこれ。>http://www.mail-archive.com/classpath-patches@gnu.org/msg08501.html

さらに、こっちのドキュメントは詳細だしバグにも触れてある。上のスレッドで報告されてるのとは別のバグみたいだけど。

boolean hitEnd()

(This method is unreliable in Java 1.5; a workaround is presented on page 392.)

This method indicates whether the regex engine tried to inspect beyond the trailing end of the input during the previous match attempt (regardless of whether that attempt was ultimately successful). This includes the inspection done by boundaries such as \b and $.

If hitEnd returns true, more input could have changed the result (changed failure to success, changed success to failure, or changed the span of text matched). On the other hand, false means that the results from the previous attempt were derived solely from the input the regex engine had to work with, and, as such, appending additional text could not have changed the result.

The common application is that if you have a successful match after which hitEnd is true, you need to wait for more input before committing to a decision. If you have a failed match attempt and hitEnd is true, you'll want to allow more input to come in, rather than aborting with a syntax error.

本日のツッコミ(全4件)
ds14050 2012年09月16日 (日) 18:56 JST

>ところで、hitEnd()が trueかつ requireEnd()が trueの場合って存在するだろうか。<br><br>alternative(|)の左パターンが hitEndしつつ失敗。右パターンが requireEndしつつ成功、とか?<br><br>>hitEnd()も、マッチが成功していたときは重要ではない。<br><br>重要。最長のマッチを見逃さないためには hitEndが trueである限り入力を延長し続ける必要があり、hitEndなしでは中途半端な長さのマッチで満足してしまいかねない。requireEndとは違いマッチの後端が文字列の末尾にかかってるかどうかでは何も判断できない。

ds14050 2012年09月16日 (日) 19:16 JST

なぜだか上のコメントがスパム扱い。@data_path/log/debug.logを見た。<br><br>>I, [2012-09-16T18:56:25.076899 #73019] INFO -- : NNN.NNN.NNN.NNN->"20100531": comment contains bad words: /(?i-mx:[\/url])/<br><br>[url][/url]という独特のマークアップを使うスパムをはじくためのフィルタが誤認識してた。[\/url] ではなく \[\/url] が正しい。<br><br>ところで ECMAScript 5th ed.では文字クラスの中のスラッシュにエスケープがいらないと最近知った。わざわざルールを追加して 3rd ed.から変更されている。正規表現について知らないと JavaScriptを要素に切り分けることもできないなんて。

ds14050 2012年09月24日 (月) 02:57 JST

>[\/url] ではなく \[\/url] が正しい。<br><br>正真正銘正しいのは \[\/url\] だった。<br>しかし、文字クラスの外で閉じ角かっこにエスケープが必要だなんて、理由が説明できない。JavaScriptはもちろん、Ruby-1.9でもエスケープは不要のはず。1.8だけ。

ds14050 2012年12月07日 (金) 14:45 JST

>requireEnd()はなくても困りはしない。マッチの範囲が入力の末尾まで続いていれば無条件に入力を増やしてリトライすることで requireEnd()が trueだったのか falseだったのかは確かめられる。<br><br>先読みがあるから、マッチが入力末尾まで続いてるときに限って requireEndの戻り値を推定するというのは無意味。/(?=a$)/ とか。<br><br>ここまでのコメントをまとめると、requireEndも hitEndも必要不可欠だから存在するメソッドだってこと。