[ubuntu-jp:6130] Re: sed の正規表現

Kenzi NOIKE knoike @ gmail.com
2019年 2月 28日 (木) 13:10:01 UTC


野池です.
まったく詳しくないのですが,起きている現象に興味がありましたので,
ほんの少しだけ調べてみました.
情報提供にさえなっていないかもしれませんが,もし,考える上でのヒントになれば幸いです.

元投稿者の疑問は,

「
LC_COLLATE が ja_JP(日本語 50音表を考慮して並べ替えが行われる)ではなく
C(単純に文字コード順)であるにも関わらず,
なぜ「・(中黒)」が「ひらがなカタカナ文字」の範囲に含まれてしまっているのか
」

だと私は理解しました.(どうすれば「・」が置換できるのか,されないのか,ではなく.)
「・」は,カタカナ文字よりも大きな文字コードを持つので,範囲外のはずです.
ところが,Yoshinaga さんが示された結果をみると,確かに妙なことになっています.
LC_COLLATE が ja_JP
であれば,「何らかの理由で日本語文字を並べ替えた人が間違えたのかな?」という想像が働くのですが,LC_COLLATE が C
で起こっている現象です.


私もちょっと動作確認をしてみようと,Ubuntu の環境を用意するのをサボって,
手っ取り早く Cygwin で調べてみました.
sed のバージョンは,sed (GNU sed) 4.4 で,Yoshinaga さんの 4.5 よりも古いようです.
この sed で試してみると,Yoshinaga さんが示された結果とは異なり,
「・」は置換されませんでした.
つまり,ひらがなカタカナ文字の範囲外になっているわけで,期待通りの正しい動作です.

これと,小池さんの調査結果を合わせて想像するに,小池さんのおっしゃるとおりで,

> 結論を先に書くと、18.04以降でのsed(4.5)の文字コードの内部処理問題と思われます。

なのではないかと私も思います.

なお,sed が内部でどのような文字コード体系を使っているのか私は知らないのですが,
今回の現象では,echo の結果をパイプで渡していますので,
次の 3バイト値に対して sed は置換しようとしているのではないでしょうか.

$ echo ぁ | od -t x1
0000000 e3 81 81 0a

$ echo あ | od -t x1
0000000 e3 81 82 0a

$ echo ゞ | od -t x1
0000000 e3 82 9e 0a

$ echo ゟ | od -t x1
0000000 e3 82 9f 0a

$ echo ・ | od -t x1
0000000 e3 83 bb 0a

↓

ぁ: e38181
あ: e38182
ゞ: e3829e
ゟ: e3829f
・: e383bb




2019年2月28日(木) 21:28 toshiaki koike <t-k @ xf.pinoko.jp>:
>
> 小池と申します。
> 最近不活性なこのMLで、かつ技術よりの話題だと誰もレスしなさそうな気がしますが…
>
> 私はもうsedは使ってないので事情はわかりませんが、Perl屋の見地から。
> 結論を先に書くと、18.04以降でのsed(4.5)の文字コードの内部処理問題と思われます。
>
>  $ echo ・ | LC_COLLATE=C.UTF-8 sed -r 's/[ぁ-ゟ]/かな/'
>
> これを試してみたところ、
> 16.04(sed 4.2.2)では、
>> 18.04(sed 4.5)では、
> かな
> となりました。
>
> 一方、Perlの正規表現の場合、以下のスクリプトを実行すると、
>
> ---------------------------
> #!/usr/bin/perl -w
> use strict;
> use Encode;
> use utf8;
> my $str = qq(ABCabx123123¥・*あかさたなゑゔゝゞゕゟアカサタナ);
> $str =~ s/[\x{3041}-\x{309F}]//g;
> print encode("utf-8",$str) ,"\n";
> ---------------------------
>
> 16.04でも18.04でも、
> ABCabx123123¥・*アカサタナ
> という結果になります。
>
> ---------------------------
> #!/usr/bin/perl -w
> use strict;
> use Encode;
> use utf8;
> my $str = qq(ABCabx123123¥・*あかさたなゑゔゝゞゕゟアカサタナ);
> $str =~ s/[ぁ-ゟ]//g;
> print encode("utf-8",$str) ,"\n";
> ---------------------------
> でも同じですので、Perlの正規表現では、[ぁ-ゟ]でも[\x{3041}-\x{309F}]でも・(30FB)はその範囲外です。
>
>
> さらにsedでは、
>  echo ・ | LC_COLLATE=C.UTF-8 sed -r 's/[\u3041-\u309F]/かな/'
> を実行してみたら、16.04でも18.04でも、
>> となりました。
> 文字コードで範囲指定する場合は\u3041のような指定のほうが安全かもしれません。
>
>
> ------------------------------------ t-k @ xf.pinoko.jp 小池利明 Toshiaki Koike ------------------------------------
>
>
> On 2019 2月 27日 (水), 9:03 午後, Yoshinaga Hiroyuki <yoshinaga.hiroyuki @ nifty.com> wrote:
>
> Ubuntu というより、sed の正規表現について伺いたく投稿させてもらいます
>
> $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.10 Release: 18.10 Codename: cosmic $ sed --version sed (GNU sed) 4.5 Copyright (C) 2018 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. 作者 Jay Fenlason、 Tom Lord、 Ken Pizzini、 および Paolo Bonzini。 GNU sed home page: <https://www.gnu.org/software/sed/>. General help using GNU software: <https://www.gnu.org/gethelp/>. E-mail bug reports to: <bug-sed @ gnu.org>.
>
> といった環境で、かな文字を対象にしようとした所、
>
> $ echo ・ | LC_COLLATE=C.UTF-8 sed -r 's/[ぁ-ゟ]/かな/' かな
>
> といった結果になります ここで使った文字のコードは次のとおりで、なぜ「・」が置換されるのか解りません あ 0x3041 ゟ 0x309F ・ 0x30FB
>
> $ echo ・ | LC_COLLATE=C.UTF-8 sed -r 's/[ゞ-ゟ]/かな/'
>
> としても同じですが
>
> $ echo ・ | LC_COLLATE=C.UTF-8 sed -r 's/[あ-ゞゟ]/かな/'
>
> は大丈夫なので、「ゟ」まで跨る書き方だと「・」が含まれてしまいます この辺りの事情をご存知の方、ここより〜で質問したほうが良いといった情報をお待ちしています -- -^.~.^- 吉永博之 ~= ^ =~- yoshinaga.hiroyuki @ nifty.com ^ ~ ^ ~



-- 
// Kenzi NOIKE


ubuntu-jp メーリングリストの案内