最終更新: 2009-10-17T03:43+0900
var re = /\b/g; var match = re.exec( "012" ); alert( match.index ); //=> 0 alert( re.lastIndex ); //=> 0(ECMAScript仕様), 1(IE)
仕様では 何度 re.execを実行しても re.lastIndexが 0から増加しないから、re.execをループで実行するときにはマッチ結果が幅0のときに限り特別に lastIndexをインクリメントする処理が必要になる。
マッチの範囲は "0"の直前から "0"の直前までで、lastIndexは範囲の末尾の次の位置を指すもの。マッチの幅は0。
index = 0; lastIndex = 1; であればマッチ範囲は "0"(幅1)ということになってしまい正しくない。
index = 0; lastIndex = 0; であればマッチの幅が 0だということも、その位置が "0"の手前だということも表現できていて正しい気がする。
indexはマッチ結果のプロパティだけど、lastIndexはパターンオブジェクトのプロパティなのだ。match.index...re.lastIndexの範囲が正しいとか正しくないとかは考慮に値しないのではないか。
検索結果に影響があるかといえば、スクリプトエンジンが行ってくれないことを、スクリプトを書く人間が手作業で行っているだけなのだから影響はないだろう。
IEは至極まっとうな実装をしたと思う。
、u' '、U、U' ' というのがそれだ。早く使いたい。ところで、charより ucharの方がわかりやすくないか。char16…や char32…だとビット幅だけを規定してるみたいじゃない。……。実際にそうなんじゃないだろうか。Wikipedia(ja)には「char16_tとchar32_tであり、それぞれUTF-16とUTF-32を内部表現とする。」こうあるけど、エンコーディングを規定するのは u、U接頭辞だけ、とか。C++コンパイラにエンコーディングのバリデーションとかやってほしい人がいるとは思えないし、やらなければ内部表現云々はまるで無意味だし。……。UTF-16、UTF-32はエンコーディングではない気がしてきた(無知)。ならば Wikipedia(ja)の記述は、これらの符号化文字集合を単独で表現できる大きさ持った型だ、という意味だろうか。<< そろそろ調べどき。……。どちらも符号化方式だった。では C++0xの方を……。エンコーディングを持ってるのは文字列リテラルだけに思える。u8という接頭辞で UTF-8文字列を char配列に納められることもわかった。char16_tと char32_tについては「UTF-16とUTF-32を内部表現とする」というのは間違いで、「UTF-16、UTF-32の符号単位を格納するよう設計されている」が正しそう。「符号単位」という言葉を知らなかったのがうまく説明できなかった原因。「符号位置」(コードポイントの訳語だと思う)とは違う。
最終更新: 2009-09-25T21:30+0900
けばけばしい色づかいのカバーと紙面を埋め尽くすスクリーンショットが満載のパソコン入門書(多分に想像混じり)を置くばかりでない書店が近所にできた(ゲーデルエッシャーバッハがあった!)。というのが、1年半以上ウィッシュリストに埋もれていた本 と、パタヘネとヘネパタの違いも分からないまま、カラー印刷、紙質の良さ、遺跡の写真、JVMや GCCといったリアルな単語、教科書チックな雰囲気*を持った本 を衝動買いした理由。昨日アマゾンで Boost本とかも 2冊買ったから、食費が、が、が。
* 帯に「世界最高の教科書が全面改定。……」って書いてある。正真正銘教科書だった。
最終更新: 2013-04-29T21:18+0900
いままでは、Alt+矢印で矩形選択モードに入った後、Altを放して、それから選択範囲の拡大を(矢印で。Shiftは不要)行う必要があった。また、知らないうちに矩形選択モードに入ってしまっていて驚かされることも何度かあった。それら、Altを放す必要や知らぬ間のモード変更がなくなる。
2000年にはそのための布石というか、コメントアウトされたプレースホルダが用意されていた。そのおかげで、全くたいしたことはしてないのだけど、これまで放置されてきた理由なり原因なりを何か見落としてる?
Sakura Editor / PatchUnicode / #449 矩形選択移動コマンドの追加
俺みたいにありもののコマンドで間に合わせるのでなく、足りないコマンドの実装までされています。
今思うと矩形選択しながらの、(折り返しでない本当の)改行単位での行頭・行末移動は不要だった気がする。プレースホルダはあったけど、使わないでしょう? 改行単位の GoLineEnd自体は、矩形選択と組み合わせては使わないにしても、なくて不便だった(20120227p01.02)ので必要だけど。
残念なのは、既存ユーザーの sakura.iniには Alt+↑、Alt+↓、Alt+←、Alt+→に対する「矩形選択開始」の割り当てが既に書き込まれていること。勝手に設定を書き換えることはできないから、プログラムをアップデートしただけでは利便性の増した矩形選択に気付けない。関連するキー割り当てがデフォルトのときだけ書き換えてしまうのはありかもしれない。アップデート後1回だけ ini書き換えを実行するために、iniにフラグのための項目を増やすことが考えられる。WSHで独立したスクリプトを書く方がオーバーヘッドは少ないが、実効性は著しく下がりそう。別に隠れ機能でもいいけどね。よく使う人ほどこれまでの操作に慣れてるだろうから。ヘルプに2通りの操作があることを書いておけば気付くでしょ。でも、慣れてるけど不便だと思ってる人に気付いてもらえないなあ。俺みたいにリリースノートを嬉々として読む人間ばかりではないだろうし。
最終更新: 2016-03-05T00:30+0900
経緯 > サクラエディタBBS[r7030]
差分 > fix_cr_handling_of_regex(下に修正版がある)
お試し > sakuraW.zip (547KiB)(下に修正版がある) (正規表現検索・置換を試すには bregonig.dll(Unicode対応版)が別途必要)
検索、置換を数度試したが機能しているみたい。ただ、$ が本当に改行の手前でマッチする関係で
^.*$
を空文字列に置換するという最初に提起されたケースでは、置換後の空行までが置換対象になってしまう(置換回数が 2倍)。目的に適う、より適切なパターンは
^.+$
あるいは、エディタの行置換機能を使っているのだから、もっと単純に
.+
で良い。
「正規表現 - SakuraEditorWiki」を見ていて気付いた。\c[、\c]、\c$、\c. という制御文字のひとつを表すパターンが存在する。「鬼車 正規表現 Version 5.9.1」によれば \C-[、\C-]、\C-$、\C-.、\M-[、\M-]、\M-$、\M-. も存在しうる。\M-\C-[ なども存在しそうに思ったけど、これはこういう結果になった。
irb(main):001:0> /\M-\C-[/ SyntaxError: (irb):1: too short escaped multibyte character: /\M-\C-[/ from c:/Program Files (x86)/ActiveScriptRuby-1.9.1/bin/irb.bat:20:in `<main>' irb(main):002:0
制御文字なんて扱ったことがないからなあ(もはや relicだという認識)。対処の必要性がさっぱり感じられないけど……。
一括置換で $ が CRLFの CR直前、LF直前、LF直後(正規表現DLLに与えた文字列末尾)の三カ所にマッチしてしまうとの指摘 >サクラエディタBBS[r7039]。
逐一、置換を実行した場合は問題ないことを確認していたのだが、一括置換はライブラリに全部お任せで、検索開始位置を調整することもできないから動作が違っていたのだろう。$ が CRと LFの間にマッチするのはわかっていたが、明示的に \r を食べた場合にだけ影響があると思っていた。一括置換なんてありふれた操作でそれが明るみに出るとは思いもせず。
急いで修正 > fix_cr_handling_of_regex.rev2、sakuraW.rev2.zip (547KiB)(さらなる修正版 rev3が下に)
初めて戻り読みを使った。なんとなく反則的な手段の気がして、使わないですむ方法をいつも考えるのだけど無理だった。これで bregonig.dll依存が決定的になった。[] の入れ子のことだけなら ] が見つかったときに charset_levelを一気に 0 にするだけで BREGEXP.DLL対応もできたのだが。
\C-X、\M-X というのは Ruby向けなのかも。サクラエディタ(+bregonig.dll)で \C-[ を検索しようとすると「premature end of char-class」というメッセージが出る。となれば、\cX だけが引っかかった小骨ということになる。
対処 > fix_cr_handling_of_regex.rev3、sakuraW.rev3.zip
<追記>bregonig.dllでは \c\X が \cX の意味になるとか。もう知らねー。</追記>
個人プロジェクトでもないと色々大変そう。ドッグフードでも食べながら様子見します。とりあえず反応だけ。
2.非対応となっているBREGEXP.DLL(ANSI版)への対処方法 ANSI版とUNICODE版は別仕様としてしまうのか?
使用できる正規表現自体が別物なので BREGEXP.DLLは CBregexp::MakePattern()でよいかと。ユーザーを驚かさないための変更なので、. が \r にマッチすることを期待していた人以外に影響はないつもりでいる。
<追記>ANSI版+bregonig.dll向けのパッチを用意したので、別仕様は ANSI版+(BREGEXP.DLL/bregonig.dll)と Unicode版+bregonig.dllの間、または、 ANSI版+BREGEXP.dllと (ANSI版/Unicode版)+bregonig.dllの間のどちらでも選べる。BREGEXP.DLLのサポートするオーソドックスな(戻り読みをサポートしない)正規表現で、$を改行直後の行文字列終端にマッチさせない方法が見つからない限り BREGEXP.DLL対応は無理。</追記>
<追記>BREGEXP.DLL版も用意した。>_ANSI.rev2 >_ANSI.rev3</追記>
3.$ が改行なし最終行のEOF手前ともマッチするように改善すること $ を (?=\r\n?|(?<!\r)\n|(?<[^\r\n])$) に置き換える方法を試してみたけどエラーで動きませんでした。
肯定の戻り読みは (?<=) でした(なにせ使用経験がないもので)。気を取り直して、パターンを (?=\r\n?|(?<!\r)\n|(?<=[^\r\n])$)* に置き換えたところ、検索は予想通り、最終行がEOFのみの場合を除いて文書末にマッチするようになったのだけど、置換が行われない。(以前は行われていたのだろうか? マッチのインデックスが文書の長さと同じ(=1つはみ出した状態)になっているはずだから特別な対処が必要なのだろう)
「以前は行われていたのだろうか?」< 行われていなかった。なら、(間違ってるけど)おいておこう。
4.検索強調表示が検索時の選択反転表示と一致すること $ を (?=\r\n?|(?<!\r)\n) に置き換えた版で $ を検索すると、改行文字自体は選択反転表示にはならない(マッチしない)のに検索強調表示されている。 また、なぜか上方向検索では改行文字自体にマッチしたかのように選択反転表示になる。
$で検索したときに改行文字が強調表示されるのは、幅0のハイライトには意味がないので、実用面から今のように最低でも幅 1を保つべきだと思っていた。
上検索で改行が選択されてしまうのは間違いなので修正したい。これまでが、知らず $ が改行にマッチする仕様に依存していたのかもしれず、こういう修正は正しい方向に向かうためのものだと考えている。
修正した(rev4)。無限ループを避けるためにマッチ幅が 0のときに検索開始位置を特別にインクリメントするんだけど、そのタイミングが悪くて検索開始位置だけでなくマッチの範囲までがインクリメントされていたのが原因。
5.正規表現キーワードでの $, . 指定も検索・置換と挙動が一致すること 現状、正規表現キーワードには $, . に検索・置換でやっているような細工が入っておらず、素の正規表現ライブラリ挙動になっている模様。 検索・置換時の . の細工([^\r\n]への置換)が追加されると、今よりも差異が大きくなって混乱しそう。
すでに書いたように、. が \r にマッチすること、$ が CRLF の真ん中にマッチすることを期待していた人(いるのか?)以外は違いに気付かないだろう。
\r\n$ みたいな書き方をしていた場合にマッチしなくなる。このケースはなくはないかも。
6.検索・置換や正規表現キーワードの複数行対応への順応性
ノーチェック。sフラグが含まれる( . があらゆる文字にマッチするようになる)ときには . を置き換えないようにする、mフラグが含まれない( ^、$ が行頭、行末にマッチしなくなる)ときには $ を置き換えないようにする、とか?
>fix_cr_handling_of_regex.rev4、sakuraW.rev4.zip
2ch民は 1.6.5.0をつかうのね。♥マークはいらないんだ。Consolasも使いたくない⁑んだ。(これは俺の理由だけど) r1663を使おうぜ。
Unicode版Revision1662>http://sakura-editor.svn.sourceforge.net/viewvc/sakura-editor?view=rev&sortby=date&revision=1662
Ansi版Patch>http://sourceforge.net/tracker/?func=detail&aid=2869238&group_id=12488&atid=312488
勘違いしていた。Unicode版のサクラエディタで使用できる正規表現ライブラリは bregonig.dll(Unicode版)だけだ、という事実がいつの間にか、bregonig.dllは Unicode版専用だ、という思い込みにすり替わっていた。
だったら、採用の可否はともかく、Ansi版(trunk2の (Release|Debug)_Ansiビルドのことでなく trunkのビルド産物のこと、だろう)向けのパッチを作成する意味はあるわけだ。CBregexpのインスタンスがその寿命を通じて 1つの DLLだけを扱うのであれば、コストを初回に払うだけで、処理の振り分けを行うことができる。どっちかな?
>>> DLL初期化時に呼ばれる仮想関数がありました。(そのたびにチェックを行えばいい。実際は 1回しか呼ばれないだろう)
CheckRegexpSyntax() は癌だ。検索ボタンを押すたびに DLLのロードからはじめて、文法をチェックしたら使い捨てるって何事。文法チェックは Compile()で十分。その後の Match()のための準備にもなってちょうどいい。もろもろの手順を共通化したいのなら引数として CBregexpを受け取るべきだ。正規表現のチェックをしたい(=正規表現を利用したい)部分ではもちろん CBregexpなりなんなりをすでに持っているだろう。CheckRegexpSyntax()がこんな重量級のローカル変数をもつ必要はない。無効な検索パターンを履歴に追加したくないがために、検索の主体でない検索ダイアログが利用しているのかもしれないけど。
やっつけで一応。これで昨日書いた「コストを初回に払うだけで、処理の振り分けを行うことができる」が事実になった。昨日の段階では、検索ボタンを押すたびに DLLがサポートする文法をチェックする関数が実行されていた(初回どころではない)。これでもまだ、検索ボタンを押すたびに Compile()が 2回走るのは変わっていない。
おまけとして、bregexp.dllだけが sakura.exeの隣にある状態でエディタを起動し、その後 bregonig.dllを配置したとき、検索ダイアログでは 「bregonig.dll Ver....」と表示され、bregonig.dllしかサポートしない戻り読みを使用しても正規表現エラーにはならないものの、実際の検索には bregexp.dllが使用されるためだろう、戻り読みが機能していればマッチするはずの条件でもマッチ無しになってしまう、こういう、説明もややこしい起こりづらい状況が起こらなくなる。(文法チェックと実際の検索が CBregexpの同じインスタンスによって行われるようになるから)
本当は CBregexpが CDllHandlerを継承するのをやめて分離して、1つの CDllHandler(DLLインスタンス)を多数の CBregexp(BREGEXP構造体)から参照するのがいいのかも。もっといえば、BREGEXP構造体もコンパイル済みパターンとマッチ結果に分離したい。サポートする文法の情報はもちろん DLL付きの情報。CDllHandlerは汎用的すぎるから、その任には、CDllHandlerを継承したいまの CBregexpから BREGEXP構造体だけを追い出したものを充てればいい。
いまの CBregexpは InitDll()を呼び出されて、途中で違う正規表現ライブラリを読み込まされたとき、コンパイル済みの BREGEXP構造体を正しく解放できるのだろうか?
BREGEXP.DLLでも . と $ を置き換えるようにしてみた > fix_cr_handling_of_regex_ANSI.rev2(下に rev3)
副作用があって、XYZ(CR)(LF) という行に対して XYZを検索すると XYZ(CR)(LF) がマッチする。マッチ結果が改行に隣接しているとき、改行がマッチに含められます。$を検索すると (CR)(LF) がマッチするのは以前からの通り。ここが変わらないのは、一括置換での過剰な置換を防ぐ手立てがこれしか BREGEXP.DLLからは与えられていない、ということ。
ついでに気になった、\r\n を検索したときステータスバーに 1 bytes selected. と表示されるのを修正。>fix_selection_area_and_selected_byte_count_ANSI 選択領域が中途半端なサイズだったのも直った。それもこれも CLayoutが EOLの長さを常に 1とカウントしていたせい。マッチ範囲が勝手に 1切り詰められていた。
表示としては ↵ も ⇠ も ⇣ も同じ一字だから CLayoutのすることにも一理あるのかもしれない。それなら改行文字の部分の選択領域をせめて全角幅にして検索結果のハイライト部分と大きさをそろえよう。
ANSI版の View関連のソースを見てたら気が遠くなる。Unicode版で
あたり、なんとかならんかな。検索結果の選択範囲とハイライト領域のずれが気になる。
ANSI版を BREGEXP.DLLと組み合わせているときに、不必要に改行が検索結果に含まれてしまう場合を rev2より大幅に減らした。意地悪なパターンを与えられたときにどうなるかは把握しきれていない。
> fix_cr_handling_of_regex_ANSI.rev3(rev2と rev3にバグ発覚。rev4へ)
fix_cr_handling_of_regex_ANSI.rev4
どういうバグだったかというと、一括置換をしたときに改行や行文字列末尾付近で過剰に置換が行われないように、戻り読みが使えない BREGEXP.DLLのときは検索パターンと置換文字列に細工を施すのだけど、検索パターンの置き換え方がまずかった。
誤: /A|B/ -> /A|B((?:\r\n?|\n\r?)?)/ 正: /A|B/ -> /(?:A|B)((?:\r\n?|\n\r?)?)/
選択 | の結合順位は一番低いのでした。
バグは CBregexp.cppを好き勝手にいじっていた結果をテストしている最中にたまたま見つかった。
していた。これは単なる自己満足。
不必要に選択範囲が改行にかかっていたケースををさらに減少。> fix_cr_handling_of_regex_ANSI.rev5 検索パターンが LF直前や文字列末尾に幅0マッチしそうなときにだけ細工を行うことにした。なんというか、盆栽趣味?
バイナリ>sakura.zip
AINI版では LFCRの LFと CRの間に幅0マッチしそうなときも細工を行わないといけないだろうな。やらないけど。(LFCR?なにそれ?という立場)