Yash 2 その 296: 文字列ではないバイト列
The Open Group Base Specifications Issue 8 (POSIX.1-2024) が先日公開された。その中に以下の記載が追加されてゐる (XCU 2.5)。
Parameters can contain arbitrary byte sequences, except for the null byte. The shell shall process their values as characters only when performing operations that are described in this standard in terms of characters.
関連するバグチケットによればシェル変数に 0 以外の任意のバイトを入れられるやうに仕様を全体的に拡張したらしい。ただ、yash はプログラムの全体において変数やパラメーターをワイド文字列として扱ってをり、現在のロケール下でワイド文字に変換できないバイト列は受け入れないやうになってゐる。恐らく他のほとんどのシェル実装は多バイト文字列を多バイト文字列のままプログラム内に保持してゐるが、yash はさうではない。これを、バイト文字列を保持・処理するやうに書き換へるのは yash のほぼ全てを書き換へるやうなものなので、素直にさうすることは全く現実的でない。
もっとも、performing operations that are described in this standard in terms of characters
といふ時がどういふ条件を指してゐるのかはかなりあやふやである。シェルのほとんどの処理は文字(列)を対象に行はれるものであり、バイト列を対象に定義された処理はなかなか見当たらない。仮にパラメーターの値だけを任意のバイト列を入れられるやうに拡張したとしても、結局パラメーター以外のデータが文字列で構成されてゐるので、あまり意味がないやうに思はれる。
例へば a${foo}b
といふ単語の中にある foo といふ変数をパラメーター展開した場合、仮に foo 変数の値が文字列ではないバイト列だったとしても、結局展開後の結果は a で始まり b で終はる文字列になるのであり、文字列に変換できなかった部分は棄てるなり別字に置き換へるなりすることになる。さすがにこの結果全体を文字列ではなくバイト列として扱って文字列として不正なバイトも残すやうにするといふのはないだらう。そもそも規定はパラメーターの値をバイト列として扱へと書かれてゐるのであって、シェルが扱ふ全てのデータをバイト列にしろとは書かれてゐない。
ただ、この解釈だと実質的な変更点は環境変数の値に文字列ではないバイト列が入ってゐた場合にそれをはじくタイミングがシェルの初期化時ではなく変数を使用しようとした時に変はるだけで、実質的に結果に違ひがない。また、バイト列を文字列に変換できないときにどうすべきかはこれまで通りシェルに委ねられてゐるので、不正文字列の検出時点でさっさと撥ねてしまふこともできるだらう。
バグチケットでの議論 (メーリングリストは加入してゐないので読んでゐない) と仕様の変更箇所の内容は環境変数に関するものが主なので、基本的には環境変数をシェル変数に取り込むときの動作を気にしておけば良いのだらうが、それ以外のパラメーターに関する記述が中途半端で何をどこまで規定してゐるのか謎だ。
| 固定リンク
コメント
私は、文字ではないバイト列をどう扱うべきなのかよくわからないので、その話は気にしていないのですが
POSIX ロケールでは 8 bit すべてを扱って欲しいとは思っています。
POSIXロケールでは256個のシングルバイトを扱うことになっており、
https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap06.html#tag_06_02
RationaleによるとPOSIX.1-2008の初期版ではこの要件が明記されておらず、見落としだったとして
https://pubs.opengroup.org/onlinepubs/9799919799/xrat/V4_xbd_chap01.html#tag_21_06_02
POSIX.1-2008の2016年版で修正されています。
https://pubs.opengroup.org/onlinepubs/9699919799.2016edition/basedefs/V1_chap06.html#tag_06_02
POSIXが気にしているのも、おそらくPOSIXロケールの場合の話ではないかと思います。
投稿: ko1nksm | 2024年11月 1日 (金) 01時21分