Issue #10382 has been updated by Martin Dürst.
US-ASCII で色々例外があることは分かっています。しかし、例外を増やすのではなく、減らす方向で考えた方がいいかと思います。US-ASCII
のではなく、 UTF-8 がデフォールトソースエンコーディングとなった今では /#{‘\x80’}/
などはソースのエンコーディングを考えなかったら通らなくなりました。そこで実際に US-ASCII のではなく、ASCII-8BIT
を使いたかったら、その通りに -*- encoding: ASCII-8BIT と書けばいいかと思います。その意味で最近になって
US-ASCII を特別扱いする理由が減っていると思います。
[もともとの原因は、Ruby でソースエンコーディング以外にエンコーディングで文字列リテラルが作れないことかと思います。その為に #10391
を提案しました。]
Bug #10382: s = ‘\x80’; /#{s}/ raises an exception in US-ASCII script
- Author: Akira T.
- Status: Open
- Priority: Normal
- Assignee:
- Category:
- Target version:
- ruby -v: ruby 2.2.0dev (2014-10-14 trunk 47915) [x86_64-linux]
- Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN
以下のふたつのスクリプトの動作は一致するべきだと思うのですが、
前者と異なり後者は例外となります。
% cat z1.rb
# -*- encoding: US-ASCII -*-
r = /#{'\x80'}/
p [r, r.encoding]
% ./miniruby -v z1.rb
ruby 2.2.0dev (2014-10-14 trunk 47915) [x86_64-linux]
[/\x80/, #<Encoding:ASCII-8BIT>]
% cat z2.rb
# -*- encoding: US-ASCII -*-
s = '\x80'
r = /#{s}/
p [r, r.encoding]
% ./miniruby -v z2.rb
ruby 2.2.0dev (2014-10-14 trunk 47915) [x86_64-linux]
z2.rb:3:in `<main>': invalid multibyte escape (ArgumentError)
後者のスクリプトは前者のスクリプトの文字列 ‘\x80’ を変数に代入してから
使っているだけの違いなので動作が変わる理由はないと思います。
ここでどちらが正しいかというのが問題ですが、前者が正しいのだと思います。
正規表現リテラルはスクリプトエンコーディングというのが原則で、
それだけなら US-ASCII なので \x80 は invalid で例外という後者が正しいのですが、
US-ASCII のスクリプト内で \x80 などを使うと自動的に ASCII-8BIT になるという仕様 ruby-dev:33348
があって、
動的な正規表現に対してこれが実装されていないように思います。
(静的な正規表現に関しての実装は reg_fragment_setenc_gen だと思います。)