【PHP】下らねぇ質問はここに書き込みやがれ 15

2025/05/08(木) 21:47:46.13ID:MhxTwPG60
とはいえ、現実的に無理だからαという判断なのだと思うし、実際この方向の需要も確実にあるのも事実。
例えば
A. preg_match('/OK|NG/', ... よりも、
B. if ($str[i]==='O' && $str[i+1]==='K' || $str[i]==='N' && $str[i+1]==='G') ...
の方が(PHPでは微妙だが、少なくともCでは)速いのは確実だが、
正規表現の方が読みやすさが格段に上なので、if文だと将来的にメンテコストが上がる。
(この辺しょうもないと思うかもしれないが、Aだと見た瞬間理解《所要0.5秒》に対し、
Bだと読まないと理解できないので《所要5秒》、長期的に大規模なコードをメンテする場合はかなり問題になる。
まあこの例だと簡単すぎてイマイチだが、もっと複雑な文字列検索をif文で書くとだいぶ酷いことになる)
この為、if文記述が最速と分かっていても、正規表現『的な』、見た瞬間分かる記述で書きたい需要はある。
そしてこれをオレオレライブラリ化しても、仕様自体は正規表現的なものになってしまうので、
なら、正規表現の仕様として追加し、正規表現エンジンにやらせる、というのは、非常にもっともな解ではある。
そしてこの方向を向いているのがonigurumaではある。
2025/05/08(木) 21:48:44.34ID:MhxTwPG60
ただし俺として最高なのは、Aのソース記述をコンパイル段階でBにして最速化する、であって、
つまり全自動での最適化を望んでる。手動で手間かけてまでやりたくない。
この場合に必要なのは「明示的な『任意の最適化の許可』フラグ」だ。
これはつまり、現在 retry-limit-in-match over 等で落ちてる正規表現に対し、
「任意の最適化の許可」フラグを付ければ、「通る『事がある』」という、なんとも微妙な方向で、
制御して確実に動作させきるという、αな「正道派」からすると許容できない仕様ではある。
ただ俺は「結果が正しく、十分速ければ、何も問題ない」という、大半の、βな「ライトユーザー」的な発想であり、
バックトラックの制御なんてしたいとは全く思ってない。
ただし、問題になる箇所が後々でもすぐ分かるように、「明示的に」フラグを付ける。
結果、以後はそのフラグが付いた正規表現だけを気にしていればいい、それ以外は確実に動く、といった所。
(フラグが付いてないところはこれまでどおりの仕様で動く。
つまり、現行の動作で retry-limit-in-match over 等で落ちず、今後とも互換で同様なら、同様に落ちないことが保証される)
ある意味、「現在」確実に動かすよりも、「将来」的にメンテナンス性を上げることを優先してる。
これは上記のif文と同様、バックトラック制御を駆使して事細かに書いてる正規表現は、
単純な正規表現と比べて読むのに時間がかかるので、
バックトラック制御を追加したら同様の結果を速く得られると分かっていても、
特に問題ない箇所はできるだけ単純な記述を使うべき、とする考えになる。
《ちなみに逆の考え方は、バックトラック制御等が付加されてる程度の正規表現は一瞬で読めるように鍛えろ、となる。
あるいはBのif文記述の読み込み速度を上げろ、もありか》)
2025/05/08(木) 21:49:28.23ID:MhxTwPG60
そして一般的には、プログラマはα方向、非プログラマはβ方向を好む。
これは、プログラマは論理的理解をしてでも確実に制御しきりたいのと、
そもそもプログラマはソースコード内に記述して使うことが大前提のため、
読む回数>>>書く回数、というか、読むことに費やす時間>>>書くことに費やす時間、となるから。
だから、プログラマにとっては、多少冗長でも、すぐ読める記述のほうが好まれる。
逆に非プログラマは、まあ俺の偏見でもあるのだろうが、例えば昔に5chの正規表現スレにも書き込んだことがあるが、
かなりアウェイ感、というか、見解の相違を感じた。
どうやら連中はブラウザや蔵書検索エンジン等の「検索窓」で正規表現を使うことが主目的らしく、
基本的に正規表現はその場で使い捨て、つまり、書く時間>>>読む時間、なのだな。
だから、凄まじく記号化して、結果的に1文字でもタイプ数を減らす方を好むようだ。

等々、色々な点で大前提が違うので、プログラム板以外ではだいたい俺はアウェイで、
色々酷いことになってるが、まあそれも含めて楽しんでる。
そして上記の5chの正規表現スレ、どうやらonigurumaの連中の巣窟だったようで、
当然のごとくPCREと覇権争いをしてて勝つのはonigurumaだ、みたいな奴らだった。
俺的には、速く動けば何でもいいので、勝手にやってろ糞ウゼーとしか感じず、
よって、俺はそもそもoniguruma連中にいい感情を持ってない。
まあこれは君がここで質問するだいぶ前の事だが。
2025/05/08(木) 21:50:11.38ID:MhxTwPG60
とはいえ、VSCodeにもonigurumaが入ってるらしいので、連中が順調に成長してるのは事実だ。
もしかするとRuby以上にいい線行ってるかも、とも思う。
とはいえ、αの方向はどうなの?とはかなり疑問ではある。
現行の先読み/後読み等もそれなりにややこしいので、
そもそも論理的理解力が乏しい非プログラマ連中にはかなり向いてない。
結果、現在もいるであろう、「正規表現だけしか出来ない馬鹿」を余計にのさばらせるだけではある。
2025/05/08(木) 21:50:33.88ID:MhxTwPG60
まあこれに関しては余談になるが、
ずいぶん昔にコメントアウトの /* */ を正規表現で削除する処理する、というブログページがあって、(とはいえ今検索しても出てこないんだが)
曰く、単純に preg_replace するだけでは、内部に任意のコメントを書かれたときに対応出来ない、
だからコメントとしてこういう文字列を書かれた場合に対応するためにこう、そしてこう、、、、と続き、
最終的にこれだ!!!これで何をコメントされても完璧に動く!!!
というのがあって、この程度書けないようなやつは困る(キリッ、みたいな締めになっていたが、
うむ、なるほど、俺には読めんな、とは思った。(結果忘れてここに書けないのはすまん)
しかしこれ、そもそもコメント /* */ なんて正規表現以前の時代の産物で、
当然その時代のコンパイラでも問題なく処理できる仕様となっており、
実際、whileとif文でなら(面倒ではあるが)馬鹿みたいに簡単に書ける。
だから、プログラマには「whileとif文で書く」というオプションがあり、
(あるいは、被検索文字列を前処理したり、正規表現処理を複数回に分けたり等の、プログラムを書く事も可能)
結果的に正規表現を極めきる必要はなく、
世間と同程度の正規表現を読み書き出来ればまあ問題ない。
この点、「検索窓」ではどうにもならないので、非プログラマは何がなんでも「正規表現で一撃で済ませる」必要があり、
結果的に正規表現を極める奴が出てきて、
そいつらからすると俺らプログラマはなんとも中途半端な理解に見えるようだ。
2025/05/08(木) 21:51:02.34ID:MhxTwPG60
結果、「プログラマ」連中は、ソースコードに書かれてる程度の正規表現は読める必要があるが、
過度な正規表現は他のプログラマが読めないので禁止であり、中庸の正規表現の使用に落ち着く。(これがPCRE程度、というのが多分一つの目安)
非プログラマ連中は、極めた「匠」となり、なんでも正規表現でやり切るか、
「正規表現書けるの?すごーい!!!」程度の「ウルトラライト」に二極化する。(勿論断然多いのは後者)
なので、α方向は実際どうなのよ?はかなり疑問である。
現実的に現在のPCREな正規表現だと色々足りてないのは事実だが、
onigurumaなバックトラック制御を今後もてんこ盛りな方向だと、
結局読みにくい(=読むのに数十秒かかる)正規表現になってしまう気もする。
プログラマ的には、正規表現と、if文と、読みやすい方を選べばいいだけではあるので、使わなければいい、ではあるが。
ただ件のスレのoniguruma連中は、「匠」なので、α一択なのだろうけど。
俺としては、つべこべ言わず動けばいいだけなので、問題になってる正規表現にだけ明示的に「任意の最適化の許可」付けて、
結果的に動作し、バックトラック制御なんてしなくて済むほうが助かるが。
2025/05/08(木) 21:51:33.26ID:MhxTwPG60
さて読んでて思ったのだが、これ、仕様が矛盾してて、現実的に実装できない可能性も有るのでは?
これは当人も気づいてて言及してるが、実際に矛盾してるかどうかまでは分からないようだ。
> JS also ensures that /\w/iu is the inverse of /\W/iu. (https://github.com/kkos/oniguruma/issues/351#issuecomment-2818389363)
俺も考えてみたが、よく分からん。
単純には、[\w]!==[^\W]でどうにも実装できないケースがあれば、
どのみちいつか breaking change するしか無いので、後腐れなく出来るのだが。

ところで同様の問題は、多分「濁点」にもある。
(この板がunicode許可してるかは知らんので以下見た目意味不明になるかもだが)
Unicodeには、結合文字用濁点(0x3099)があるので、「あ゙」とかも出来る。(表示系が対応してれば前の字と重ねて表示され、あに濁点がつく)
よって、「が(0x304c)」と「が(0x304b,0x3099)」は見た目区別がつかない。
(0x304b,0x3099を表示するのに、通常は、単純にビットマップを重ねるわけではなく、0x304cのフォントが使用されるから)
おそらくこの辺もonigurumaは対策されてるのではないかと思う。
正直、これはヒットしてくれたほうが助かるのは事実。
というかね、ブラウザ(Ctrl+F)ではヒットするが、JSではヒットしないので、
見た目表示されてるのにJSから検索すると存在せず、あれ?ってなったことがあった。

だから見た目、現行の動作は、「仕様的に正しい」。
これは本当に重要で、先日も言ったが、仕様を追加するのはいつでも楽勝だが、削除するのは基本的に無理なので、
おかしな仕様を追加した時点で将来的に詰むのが確約されるから、これは全力で回避しなければならない。
現行の動作は、確かに正しい。
問題は、その場合に異常に遅くなるケースがある、ということであって、
本来は、仕様変更ではなく、速度対策『だけ』で済ませるべき状況であり、実際に高速化すれば何も問題なくなるはず。
とはいえ高速化はもう出来ません、ということなのだろうが、果たしてそうなのか?とは思う。
2025/05/08(木) 21:51:59.95ID:MhxTwPG60
例えば典型的な糞ッタレ正規表現、
> a.*b.*c.*d.*e // --- (a)
についてだが、
> a.*+b.*+c.*+d.*+e // --- (b)
は確かに一つの解だろう。しかしこれは、最速ではない。
人間がやるときを考えれば分かるが、

$len = strlen($str); // ---(c)
$e = strrpos($str,'e'); // 最後のe
$d = strrpos($str,'d',$e-$len); // eより前の最後のd
$c = strrpos($str,'c',$d-$len); // dより前の最後のc
$b = strrpos($str,'b',$c-$len); // cより前の最後のb
$a = strpos($str,'a',$b-$len); // 最初のa
if ($a<$b) // check

と後ろから検索するのが速く、正規表現にすると

/(?<=(a.*))(?<=b.*?)(?<=c.*?)(?<=d.*?)(?<=e(.*?))$/ --- (d)

となる。が、まあ、(d)だと得られる結果が微妙に異なってしまうので後処理必要だが、(というより同じ結果を得られる正規表現を書けなかったorz)
内部的に自動的にこの方向で高速化してくれ、となる。
単純には、greedyに対してnon-greedyで右から検索すれば多分最速になる。
この辺、バックトラックの指定を事細かく出来る=走査順が仕様として規定されてしまう=左から右に走査、となってしまってるのが問題なので、
「任意の最適化の許可」フラグで、右から左に走査することも許可し、(勿論それ以外にもやっていい)
結果的にクソ速いがバックトラック制御は出来ませんよ、が正しい気がする。
(フラグ指定した場合、どう走査されるかはエンジン任せで、
結果的にバックトラック制御を指定してもどう動くか予想できず、実質使えなくなる。
が、問題は速度が遅いことであり、バックトラック制御をするのが目的ではないのでこれでいいはず)
2025/05/08(木) 21:52:39.44ID:MhxTwPG60
ちょっと伝わりにくいだろうからもう一度書いておくと、俺の希望としては、
プログラマがコードとして書くのは(a)で、
これを内部的に(c)で処理して最速化しろ、
処理順だけ書けば(d)になるが、この正規表現では読むのに時間がかかる(所要30秒)ので無理、
「匠」は(b)を書くが、これは(a)よりは理解に時間がかかる(所要10秒)し実行速度も最速ではない。
「プログラマ」は(a)で無理なら最速の(c)プログラムを書くが、
(a)は2秒で理解出来るのに対して、
(c)見て(a)と理解するには1分かかるので、前述のとおり、これをプログラム全域にまぶすと後々詰む。
最低限、(c)の先頭行に、// /a.*b.*c.*d.*e/ を高速化した とコメントがないと死ねる。
しかし結局、(a)の処理が速ければ最初から何も問題ないので、目指す仕様はここで、内部的に頑張ってくれ、という事。
ユーザーに「匠」となり、最適な正規表現を精巧に作り上げることを要求するのではなくてね。
(だから仕様追加するなら「後ろから検索」フラグ、でもいい。
そして /e.*?d.*?c.*?b.?a/Backwards で(a)と同様の結果が得られるとかでも)
2025/05/08(木) 21:53:03.02ID:MhxTwPG60
とにかく、ユーザーが困っているのは「仕様」ではなく「実行速度」なのだから、
それを「仕様」の限定化(仕様縮小=スペックダウン)で回避するのは悪手であり、まず高速化をやるのが先だ。
あるいは \U のように、unicode対策を外すフラグ付加(=フラグ付加時のみ仕様縮小での高速化)で対応できる。
kkos氏はこの仕様が実行速度に多大な影響を及ぼしているのを知っており、元々外したいと思ってたのだろうがね。
しかし、この状況で「仕様」を変更するのは、一般論としては明確な間違いだ。
何度も言ってるが、今の仕様は正しいので。
(とはいえ、結局この辺の采配、つまり理想と現実の兼ね合いでどう仕様を決めていくかが最終的な繁栄/衰退につながるので、
勿論kkos氏が決めるべきだし、実際、この仕様を捨てたら爆速化して更に支持率ダダ上がり、の可能性もある。
まあこの辺の采配を間違えたのがRubyと見てるが、onigurumaは果たしてどうなるか、といった所)
2025/05/08(木) 21:53:24.95ID:MhxTwPG60
> Therefore, choices for elements other than the character class are generated after the character class.
ちなみにこの意味が分からない。(が、#350にもそのまま転載されてるから彼らの中では通じてるのだとは思う)
これって具体的にどういう意味か分かる?
/(?i)[\S]/ を
/(?-i)(?:s|t|st|ss)/ ではなく、
/(?-i)(?:ss|st|s|t)/ (greedyなので長いほうが先、ついでにアルファベット順でssの方が先)
と見なす(に近い)ということか?

以下 https://github.com/kkos/oniguruma/issues/351#issue-3005666017 内について
> [r`(?i)^[\w]$`, 'ss'], // ✅
> [r`(?i)^[^\W]$`, 'ss'], // ❌ ← むしろこれがアウトだろ、疑問マーク付いてないが
>
> // The negation rule is about negation of the outermost class, only 🤔 ← この解釈が間違いで、
> [r`(?i)^[[^\W]]$`, 'ss'], // ✅ 🤯 ← これと
> [r`(?i)^[\w&&[^\W]]$`, 'ss'], // ✅ 🤯 ← これには俺は問題を感じない
> // In the reverse direction with quantifiers; nothing surprising here ← いや、
> [r`(?i)^s{2}$`, 'ß'], // ❌ ← これはヒットするべきでは?
と思うが、まあこの辺は互換性もあり、なかなか変更できないのだとは思う。
2025/05/08(木) 21:54:13.31ID:MhxTwPG60
以降は前回の話について
(途中まで書いてたのに付け足してるので時系列的にちぐはぐかもだが。
あと若干、何まで書いたのか忘れてるので、重複も有るかも?)

> 名前が見つからずにエラーになる原因は oniguruma に "FAIL" や
> "SKIP" などが登録される前に callout_name_find されているのが原因でした
つまりonigurumaの「登録」(初期化ルーチン)と「検索」(phpのmb_ereg_replace)が
レーシングしていて(通常「競合」と訳されてるようだが、個人的には「競争」と訳すべきだと思っている)
fprintfのおかげで偶々運良く上手く行く方向に変わったわけだ。
(まあ一般的にレーシングの場合は再現性が低い=ちょっと条件を変えたらすぐ収まってしまうので、こういうこともよくある。後述)
2025/05/08(木) 21:54:36.67ID:MhxTwPG60
> C言語のことを知りたいなら本なりで基礎から学ばないとダメですね
そうだが、実際の所、何となく読めるはず。
理由は簡単で、C言語は現在のメジャー言語全部の下敷きになっており、
文法はメジャー言語から見ればスモールセットでしかないから。
実際学んでも、ifとforとwhileだけですかー、と何も無さ過ぎてビビるはず。
ただしポインタを生で使える点だけが違う。
(とはいえphpでも全容を把握する為にはポインタの理解はある程度必要なので、
逆に言えばphpを完全理解してるのなら《知識的な》修得自体は容易。
phpで言うと、配列を「値渡し」して関数内で変更しても、元の配列は変更されないので、
変更したい場合は「参照渡し」しなさい、となってるが、その辺)

C言語は基本的に一対一でアセンブラに落ちるので、高級アセンブラのようなものではある。
だからC言語はCPUの動作そのものに近く、プログラミングにおいてはベースの前提知識として役立つ。
結果、どの言語を学ぶにしても見通しがよくなり、修得が早くなる。
だから職業プログラマを目指すなら、できるだけ早い段階でやっておいた方がいいし、
実際、大学のCS系では今でも1年生の時期にやってるはず。
何だかんだでベースの前提知識として役立つ。
2025/05/08(木) 21:55:17.31ID:MhxTwPG60
というのを11月に思ってたのだが、(特定する気もないので該当するかどうかを答える必要はないが)
もし君が学生で、職業プログラマを目指しているのなら、今すぐにでもCをやるべきだ。
理由は上記のとおり、上達速度が上がるから。
なんかね、君の「知識/経験」と「能力/実力」のアンバランスさが異常で、正直俺は遭遇した事がないレベル。
「やってみたら出来ちゃった」的に話が進んで行ってるのが異常で、
普通は知らない言語の時点で諦めるし、勿論環境も立ち上げない。
こういうの無視して闇雲に突撃したところで成果も出ない。
ある程度年取って「分別のある」プログラマなら、この辺知ってるから、突撃もしない。
だから無鉄砲に突っ込んで結果まで出してるのはかなりありえない展開で、
俺が思いつくのは、あまりにも若すぎて、自分の実力を認識できてない、とかだね。
まあスポーツ選手にしろアーティストにしろ20代そこそこで世界に駆け上がっていくので、
本当に実力のある若者はこんなものなのかな?程度に思ってる。
君は俺のアシストが効いたと思ってるのだろうが、そうじゃない、それは明らかに君の実力だ。
確かに今回はラッキーもあったが、GitHubでまともに議論参加できてるし、実力の片鱗は見えまくり、といった所。
2025/05/08(木) 21:55:29.47ID:MhxTwPG60
ただし、C言語の「理解」が目的で、C言語を「極める」必要はないことに留意すること。
C言語が50年も現役で居続けられるのは仕様/構成が素晴らしいからであり、この理由を理解するのは重要だが、
今C言語を書く必要がなければ、達人である必要はなく、当然書ける必要もない、
というか、Cにも問題が多々あったから、Cをベースとして他言語が発達してて、
つまりCの駄目なところは他言語使えばだいたい解決してる。だからCを書くこと自体に苦労する必要はない。
ただし、どういう思想でどういうコードを要求してる言語なのかを理解することは本当に重要。
まあこれでは分かりにくいので一つ例を上げると、「ポインタ」になる。
「ポインタ」の概念を理解できてて、他言語でも、ああこれは「ポインタ」だね、と分かることはかなり重要。
ただし、「ポインタ」を使いこなして、素晴らしいCコードを書ける必要はない、という事。
まあ「ポインタ」はよく言われるけど、その他も、例えば変数のライフタイムとかうまく出来ており、
Cの仕様は、「確かにこれしかない」と思えるものなので、無駄のないコードをどう書くかの参考にはかなりなる。
2025/05/08(木) 21:56:10.52ID:MhxTwPG60
さて話を戻すと、onigurumaはC界隈でもあまりやってはいけないとされている「マクロ芸」をやってる。
だからCマクロを知らないと読めないが、これはoniguruma側の問題だ。
(なおC++ではCの問題はCマクロで色々誤魔化せる事だとし、
Cマクロが使われる状況毎にC++文法を用意し、これを使う事でCマクロの除去を目指している。
だからC++ではCマクロは禁忌とされてる。
《と言っても『当初の』C++は、で、その後明後日の方向に暴走してたが》)

Cマクロは「ソースコードを直接書き換える」ので強力だが、結果、
「プログラマが見てるコード」とコンパイラで「実際に使用されるコード」が異なる事が大問題だとされてる。
なので、注意喚起、つまり、
「お前が今見てるコードと実際使われるコードは『別物だ』」と
『見た瞬間』分かるように全部大文字で書け、とされている。
だから小文字マクロは可読性の意味では完全にアウト。
(といってもLinuxコードには使われまくってるのだが、
あれはこういう決まり事が出来る前の産物だし、
また、小文字マクロでも可読性を損なってないのも凄いのだが)
2025/05/08(木) 21:56:36.96ID:MhxTwPG60
onigurumaで小文字マクロが大量に使われてるのは、おそらく大改修中だからだ。
全部大文字マクロに変更して変更箇所が膨大になるよりは、小文字のままで行ったほうが混乱しないと踏んだのだろう。
そして今回は初期化ルーチンのレーシングだが、こうなったのは仕様が変更されたから。
単体のonigurumaの使い方は分からんが、PHPで言うと、

当初:CGIで、毎回PHPを起動しては全部捨てる(各PHP毎にonig_initを呼ぶ)
今:モジュールで、一度PHPを起動したら常駐(初回にonig_initializeを呼んで以降は呼ばない)

レーシングしてたのは改修中で整合性取れてなかったのか、単に変更忘れててバグってたか知らんが。
そして条件を変えたら直ってしまった、というのは運だが、そこから追跡して原因まで到達してるのだから順当に実力だ。
ただもっと運が良ければ、例えばlaravelとか使ってたら、最初から動いていたかもだが。
つまり、レーシング自体はかなり微妙な場合も多い為、
mb_xxxxを呼ぶ前にlaravelのコードを大量に処理すると、これだけで動く方に倒れてたかもしれない、ということ。
ただこの場合、再現性が低くなり、(=俺の環境では問題ないが続出、あるいはlaravelのバージョン毎に出たり出なかったり)
デバッグには相当手こずるので、
まあ状況不明だが、デバッグ出来たのは、kkos氏にとっても意味はかなり大きいとは思う。
後は、上記の通りCGI環境でやってれば、onig_initで問題なく、最初から動いていた可能性もある。
(まあここら辺は運だが)
2025/05/08(木) 21:57:49.64ID:MhxTwPG60
あとちなみに、(*FAIL)が辞書にない=(*FAIL)も辞書登録する、ということであって、
つまりonigurumaは(*FAIL)もユーザーが動作を上書きできるようにしてる。
普通はこの辺はリテラルで与えるので、登録されてねえ…ってことには構造的にならないんだけどね。
まあこの辺はkkos氏のポリシーなんだろう。


てな感じ。まあぶっちゃけだいぶ忘れちゃってるのを色々覚えで書いてるし、どこまで投稿したかも忘れてるので、
重複があったり、間違ってたらごめん。
2025/05/10(土) 22:48:40.31ID:4QcnHpbT0
補足

実際にコンパイラ/インタプリタの実処理系で
「特定の文字列が含まれたソースコードは開けない/動かない」なんてことは聞いたことがないので、
これらでは仕様策定時の想定通り、if文で処理してる。
だからシンタックスハイライターで正規表現を使うのは手抜きでしかないが、
>>57の通り、この手抜きをやって新しい文法により早く対応することを優先するのは正しい。
(全部if文で書け、なんて言われたらシンタックスハイライターをメンテするやつが居なくなる)


>>61は、
✕ 内部に任意のコメントを書かれたときに
○ コメントを書かれるあらゆる状況に
だったかも。/*が''等で囲まれてる場合には単純に/* */を除去しても駄目。

echo '/*aaa*/'.''/*bbb*/.''; // PHP: /*aaa*/
console.log('/*aaa*/'+''/*bbb*/); // JS: /*aaa*/
2025/05/10(土) 22:50:50.89ID:4QcnHpbT0
>>63-66
仕様変更は https://github.com/kkos/oniguruma/issues/351#issuecomment-2816719627 に付け加えると

1. 全部諦める ← kkos氏の選択
2. モードスイッチでコンパイル時に切り替える
3. \U フラグ等で動作時に切り替える
4. 現行通り、[\s\S]!==. (つまり現行は中途半端な仕様になってる)
5. [\s\S]===. となるように仕様をアップグレードする

で、俺は5が良いと思ってる。これが正しい仕様だから。
しかしこれが速度的に無理なら、遅くなる正規表現にだけフラグ付けておき、
プログラマはアップグレードの度にそのフラグの除去を試し、最終的にこのフラグを全部除去する、の方が良いと思う。
ただ、現実的にシンタックスハイライター等での使用なら \U の方が手っ取り早いので、3も良い解だとは思う。
1.は良い解だとは思わない。

要は、速度の問題は内部最適化で隠蔽し、外面仕様に出すな、という事。
そしてトラックバックの制御を出来るようにする=内部走査順が外面仕様に出る=最適化ができなくなる、ので、
現行のトラックバック制御の仕様追加もいいとは全く思わない。
将来的にCPUがもっと爆速になって、放っておいても問題なくなったときに、糞ウザい正規表現のコードが残るだけ。
(とはいえ、現状、CPUが爆速になっていく見込みなんてないのも事実だが)
2025/05/14(水) 23:27:01.41ID:UpG0dv4Tr
凡人エセプログラマーの私にはあなたが一体何をしているのかさっぱりわかりません
何やらすごいことをしているのは空気でわかります
しかし宇宙語並に理解不能なのでよければ軽く解説してくださるとうれぴいです
2025/05/18(日) 12:03:54.19ID:miJJONwf0
>>50
遅くなってすみません、やっと全部把握出来たので少しづつレスしていきます。

>>77
PHPのmbstringのmb_ereg()系の関数に使われている正規表現エンジンのOnigurumaが先月開発終了となりました。
その原因は /\w/i と /[\w]/i の動作が一致しない等の不整合があり、fixが手間的に難しいということでした。
Issue 349: https://github.com/kkos/oniguruma/issues/349

また、この問題とは別に大文字小文字を区別しない時の [\w] などが "ss" や "st" などの複数文字に一致すると
いう仕様 (これはUnicodeの仕様通りの動作) が原因で [\w]+ のように繰り返しなどを使った場合に
バックトラックが大量発生するケースがあり、本来ならマッチすべきケースでもエラーを出して検索が
止まってしまう場合がある、という問題があります。
Issue 351: https://github.com/kkos/oniguruma/issues/351

例えば検索される側のテキストデータに "sssssssss" などが入っていると [\w] に対して "s" 1文字が
マッチする場合と "ss" の2文字がマッチする場合の2種類を試すことになります。
この動作に繰り返し処理が加わることでバックトラックが発生した場合にものすごい試行回数になる場合があります。

50さん(超優秀な方)はこの2つの問題についての見解を書いて下さっています。

この件に関するPHPのてきとうなリンク
https://tekitoh-memdhoi.info/views/919
https://github.com/php/php-src/issues/18467
2025/05/18(日) 21:38:45.86ID:miJJONwf0
>> 個人的にはもしPHPが再び Oniguruma を取り込む場合は fix_351_349 ブランチ を取り込むことをおすすめします。
>PHPは互換重視、というより、互換絶対、だ。だから厳しいだろう。

了解です。私は頓珍漢なことを言っていたようです、すみません。

> 昨日mergeしたのか?

いえ、これは私がOnigurumaをforkしたリポジトリでのmargeです。
このmargeは不適切ということでforkしたリポジトリは削除しました、ご指摘ありがとうございました。
(セキュリティ上の理由でforkしたリポジトリは非表示に出来ないようです)

> fix_351_349ブランチ

現時点ではこの動作の切り替えは以下のマクロでしているようです。

#ifdef USE_DIFFERENT_CHAR_LENGTH_MATCH_BY_IGNORECASE
https://github.com/kkos/oniguruma/blob/5d0506c66c4d3613912fa81d7d1b99f83dbea8e2/src/regcomp.c#L4767

>> Therefore, choices for elements other than the character class are generated after the character class.
>ちなみにこの意味が分からない。

これは /(?i)[\S]/ を /(?-i)(?:s|t|st|ss)/ とみなす、だと思います。
"s|t" に続いて "st" と "ss" の選択肢が追加されるという意味だと思います。
2025/05/18(日) 21:43:53.82ID:miJJONwf0
> [r`(?i)^[^\W]$`, 'ss'], // ❌ ← むしろこれがアウトだろ、疑問マーク付いてないが

これはOnigurumaの最適化によって /(?i)^\w$/ として扱われていると思われます。

> // The negation rule is about negation of the outermost class, only 🤔 ← この解釈が間違いで、
> [r`(?i)^[[^\W]]$`, 'ss'], // ✅ 🤯 ← これと
> [r`(?i)^[\w&&[^\W]]$`, 'ss'], // ✅ 🤯 ← これには俺は問題を感じない

これはおっしゃる通りだと思います、解釈の間違いですね。

> [r`(?i)^s{2}$`, 'ß'], // ❌ ← これはヒットするべきでは?

確かにUnicodeの仕様上ではマッチが正しい気がしますね。ただ、こういうケースまで実装で対応するのは大変そうですね。

>「が(0x304c)」と「が(0x304b,0x3099)」... おそらくこの辺もonigurumaは対策されてるのではないかと思う。

テストしてみたところ、Oniguruma6.9.10 (UTF-8) では対応していないようです。
1. "\u304b\u3099" =~ /\x{304c}/ # マッチ失敗
2. "\u304c" =~ /\x{304b}\x{3099}/ # マッチ失敗
2025/05/20(火) 07:37:47.92ID:gP4XTsxY0
ROMってる方のために補足です。

> 1. 全部諦める ← kkos氏の選択
> 2. モードスイッチでコンパイル時に切り替える
> 3. \U フラグ等で動作時に切り替える
> 4. 現行通り、[\s\S]!==. (つまり現行は中途半端な仕様になってる)
> 5. [\s\S]===. となるように仕様をアップグレードする

これは大文字小文字を区別しない場合の話です。

次に、3. の "\U" について。
Issue 351の以下のコメントでは "\U" を "\w" や "\d" のような文字集合の一種として使っています。
github.com/kkos/oniguruma/issues/351#issuecomment-2816719627
このコメントでの "\U" は全ての1文字にマッチするだけでなく、"ss" や "st" などの特殊な複数文字にもマッチする、という仕様のメタ文字です。

5. の "[\s\S]===." は /[\s\S]/i と /./i が共に "ss" や "st" などの特殊な複数文字にもマッチする仕様にする、という意味です。
Oniguruma6.9.10 では /./i は "ss" や "st" にはマッチしませんが、/[\S]/i はこれらにマッチします。これについては以下のコメントをご覧ください。
github.com/kkos/oniguruma/issues/290#issuecomment-1807145668

Unicode: 特殊な複数文字の詳細
https://www.unicode.org/Public/UNIDATA/SpecialCasing.txt

補足おわり。
82デフォルトの名無しさん (ワッチョイ 5afa-Rabv)
垢版 |
2025/05/21(水) 08:08:44.69ID:fstAuxa70
Onigurumaってそんなに関心もたれるものでもないんじゃ
2025/05/21(水) 21:44:51.62ID:/jwTY25H0
>>78
すまん#349読んでなかった。
そして#264も読んだ。


まず全般的にだが、謝る必要は全くない。
君が不味いことをしたわけではない。
俺が偉いわけでもなく、正しいわけでもなく、決定権を持ってるわけでもない。
君は自由に、やりたいことを勝手にやればいいだけ。
俺は勝手にウダコダ言ってるだけ。正直、井戸端会議レベルだ。
GitHubは割とリアルなのである程度まともに振る舞うべきだが、5chでは死ね死ね言ってるくらいで丁度いい。
2025/05/21(水) 21:46:30.75ID:/jwTY25H0
して#349、もう辞めます!ってか。なんか割と大事(おおごと)だが。
さすがに開発元が辞めてしまったら使用者側としてはどうにも動きづらいだろう。
一般的に、またPHP的に、ありがたいケースは順に、
・辞めるの止めます、で復帰してくれてそのまま開発継続
・主たるcontributorの誰かがforkして、大部分のcontributorがそこに集まって開発継続
・複数のforkでそれぞれ開発が行われ、その中で良さげなものを探して使う
・誰もforkしない、または使えそうなforkがないので、ひたすら現行バージョンを使う
 (バグがあってもそのまま、セキュリティ的に問題があれば落とされるかも?)
かな?
まあ今の採用バージョン知らんが、Version6.9.10を入れてからその先の話だから、だいぶ猶予はあるけども。

しかし唐突というか、なんだかねー。
大体文句しか言われないから、もう疲れたから止めます、あるいは本末転倒になって楽しめなくなったので止めます、は分かるけど、
実装できないので止めます、はねえだろオイ!と突っ込みたくなるよ。
実際のコードは見てないが、
if文によるハードコード(速いが分量が多い)だと多種エンコードに対応するのはほぼ無理ゲーなので、
関数ポインタを編み上げるタイプのソフトコード(という言い方はあまりされないが、最速ではないがあらゆる柔軟性が確保できる)であることはほぼ確実

なので、
いろいろ容赦なく突っ込まれて嫌になったか?とも思う。(どんな仕様でも実装自体は簡単のはず《ただし速度は遅くなるが》)
しかし、言っちゃ悪いが、 s と [s] の動作が違うのは実装が悪いとは思うし、突っ込まれてもそりゃお前のせいだわ、としか。
だからまあ、forkして勝手にしやがれ!俺はもう知らん!もありではあるが。
2025/05/21(水) 21:47:16.93ID:/jwTY25H0
して、君はこれどうしたい?
普通に考えれば、最新リリースバージョンの Version6.9.10 まではPHPには入る。(いつになるかは不明だが)
だからPHPにVersion6.9.10が入れば満足なら放置でいい。
oniguruma単品で使ってて、あるいはVersion6.9.10でも不満があるのなら、
・まず仕様について積極的にcontributeしてるやつを探し、
・次にコードに対して同様にcontributeしまくってるやつを探し、
そいつらの動向を見て、みんなが集まりそうなforkに寄生して一緒に開発するのがまあ妥当。
何でもそうだが、開発には「仕様」と「コード」に詳しい奴が居ないと厳しい。
だから今の君だけで開発を牽引するのは無理ゲー。
ただし、一人でやる必要はない。
同様に宿り木を探してる連中はいるだろうし、
日本人のプロジェクトだったから日本人トップを望んでる日本人も多少は居るはずだから、
コードの良し悪しを判断できる奴を確保できれば、そいつと組んで、
君が「仕様」側のトップでツートップ/多頭体制で開発継続も可能ではあるだろう。
(すまんが俺はやる気ない。PCREで間に合ってるし、oniguruma使う予定もなく、あってもv6.9.10で十分だし)
まあ5chの正規表現スレ(どこだったかは忘れたが)にたむろしてた連中も大騒ぎしてるだろうし、
そいつらからもリクルートできるのではないかと。
(連中が仕様に詳しいのは確かだが、コードは書けない感じだし、
そもそも人格や報連相に問題があるかもだが、これら含めてOSSだしそんなもん。
開発者がいきなり交通事故で死ぬこともあるのだから、細かい文句を言ってても始まらん)
2025/05/21(水) 21:48:36.13ID:/jwTY25H0
> 了解です。私は頓珍漢なことを言っていたようです、すみません。 (>>79)
いや謝る必要はまったくない。
ただ、PHP程の歴史があると、仕様変更は結局、
・これまでのコードをメンテしないといけなくなる連中がパニくるため、
・クソ仕様をさっさと更新して欲しい「ご新規さん」は少数派で、多数決的に勝つのは無理
・だからクソ仕様が周知されてて、界隈で「いい加減直そうぜ」とならないと仕様変更されない
 (なのでPHP8で修正された事項も『皆さんご存知のクソ仕様』ばかりのはず。onigurumaはこれに程遠い)

> いえ、これは私がOnigurumaをforkしたリポジトリでのmargeです。
> このmargeは不適切ということでforkしたリポジトリは削除しました、ご指摘ありがとうございました。
> (セキュリティ上の理由でforkしたリポジトリは非表示に出来ないようです)
これもGitHubの仕様が全く意味不明だ。
forkはただのローカルコピーだからしていい、というかむしろやるべきだし、
そもそも好き勝手するためにforkするのだから、何やってもfork元には迷惑はかからないし、issueトラッカーに表示されるのもおかしい。
この辺全く知らないが、もしかすると、宿り木を探してる連中のために、
archive化されたリポジトリについては〇〇が引き継ぐみたいだぞ!と見えるようにしてるのかもしれんが、
仮にそうであっても、forkして自分にとって都合のいいmergeを行って何ら問題ない。
(というか、セキュリティ上の理由って何ぞそれ?ではある。垢無しで全世界公開なのにセキュリティもクソもねえ)

> #ifdef USE_DIFFERENT_CHAR_LENGTH_MATCH_BY_IGNORECASE
#ifdefだからコンパイル時に切り替えだね。
ただコード見る限り、俺が想定してたのとはだいぶ違う。(いいか悪いかは別、というかそこまで読んでない)

> ただ、こういうケースまで実装で対応するのは大変そうですね。
実は動かすだけなら言うほど難しくはない。(現実的な速度が出るかは別問題だが)
ただし分量が死ぬほど多いので、仕様をよく知ってるやつがやらないと話にならない。
(バグ報告〜修正の往復の方が実装の手間を遥かに超えてしまう)
2025/05/21(水) 21:50:00.51ID:/jwTY25H0
>>82
正規表現ライブラリの問題は、多分「仕様」側と「実装」側が乖離してる事。(これは他の非プログラマ向けソフトも同様だが)
正規表現の使用対象をざっくり二分すると
・ソースコード
・自然言語
で、「実装」側、つまりプログラマは前者なのでasciiが通ればほぼ問題ない。
PHPではユーザー入力やDB登録されてるテキストが後者になるので、多少は取り扱うけども、
基本はGUIのサポートなので、ハズレたらハズレたで問題ない程度でしかない。
それよりは、自動(正規表現はソースコード内)で使うので爆速な事が必要。
「仕様」側、例えば文献検索で小説本文から対象文字列を抜く、回数を数える、みたいな使い方だと、抜けがあったらそれなりに困る。
ßはssにヒットしないと、使い物にならない。
ただこちらは基本的に手動(正規表現は手打ち)なので、人間が我慢出来る速度なら問題ない。

だから、求められる正規表現ライブラリの仕様は、
プログラマ向け:ascii専用でいいから爆速
非プログラマ向け:unicode規約に則った、自然言語対応型。速度は遅くても構わない
で、おそらくonigurumaも基本は前者で、
ついでに後者向けにunicode規約満たしてみたら(多分だが他が全く対応してないので)
自然言語を取り扱う連中には重宝され、あちこちに採用されたはいいが、「これはバグですか?」的な報告が大量に来る事となり、
kkos氏自身はasciiだけで満足出来る側だったので「もう知らん」になったとか、かと(全部推測ですが)

だからプログラマはPCREで満足してて、mb_xxxのonigurumaにはあまり関心がない。
使ってなく、使う予定もないから。
2025/05/22(木) 02:35:12.36ID:muJghNBDr
>>78
ご説明ありがとうです。
ChatGPTに聞きながら読んでみたけど、結論正規表現的には日本語はクソって言ってました。
とにかく恐ろしいほどの苦労があることはわかりました。
2025/05/23(金) 20:54:03.48ID:uUJ622wJ0
>して、君はこれどうしたい?

正規表現についてはもう十分な知識を得られたと思うので次は教えて頂いた通りに
C言語を本格的に始めてみようと思います。以降スレ違いになるのでこちらでお願いします。

c言語教えてくれ
https://mevius.5ch.net/test/read.cgi/tech/1728823763/

PHPスレのみなさまありがとうございました。お邪魔しました。
90デフォルトの名無しさん (ワッチョイ 655f-AFj/)
垢版 |
2025/06/20(金) 15:02:33.00ID:zfoKSuMt0
配列について教えてくださいーーー
DBでSELECTして得た結果を$array1に受けて処理した後にMoveNext()の直前でその配列を$array2にコピーしています。
それによって前の行と内容が同じかどうかを判断したいのです。
しかしMoveNext()をするとコピー先の$array2の内容も$array1と同じように次のレコードに変わってしまいます。
(参照渡しはしてないのです。)
何故なのでしょう!?

$array1 = $db=>Execube (....);
while (!$array1->EOF) {
 if ($array1->fields['xxx'] == $array2->fields['xxx']) {
  ...
 }
 ......
 ......
 ......
 $array2 = $array1;
 $array1->MoveNext();
}
2025/06/20(金) 15:46:56.39ID:Mw7W7PWm0
>(参照渡しはしてないのです。)

参照渡しをしているのに よくもそんなことを言えたものだな
2025/06/21(土) 00:25:41.04ID:4ubedfeT0
あぁ...オブジェクトを値渡しするにはcloneが必要なのですね
レスを投稿する

5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況