The requested blog was not found -- unless you requested that of Dan Kogai (小飼 弾).
まずは回答から。
正規表現で「制御文字以外」のチェック - ockeghem(徳丸浩)の日記このうち後ろ二つを正規表現として書くにはどうすればいいかを考えていました。
- 文字エンコーディングの妥当姓
- 制御文字(\x00〜\x1f, \x7f)のチェック
- 文字列長のチェック
こういう時には、「全文字がOKならOK」と考えるのではなく、「一文字でもNGならNG」と考えると楽になります。それは「スペースと非制御文字以外」なのですから、/[^ \S]/
が求めていた正規表現で、=~
ではなく!~
が使うべき演算子ということになります。全角スペースもOKにしたければ、/[^ \x{3000}\S]/
。[追記参照]
#!perl -luse strict;use warnings;use utf8;sub check { $_[0] !~ /[^ \x{3000}\S]/;}print 0+check("妥当な 文字列");print 0+check("妥当な 文字列"); # fullwidth spaceprint 0+check("妥当な\t文字列");print 0+check("妥当な 文字列\n");
で、今回の本題です。
残る問題は、後者についてですが、以下のサンプルプログラムは *match* を表示します。正規表現のオプションs, m, msのいずれを追加しても同じ結果でした。
- もっといい方法はないのか?
- Perlの場合末尾の\nがうまくチェックできない
の後者。実のところ、^
と$
は、フラグによって扱いがかわってしまうので利用はさけた方がよいのです。それどころか、.
まで意味がかわってしまうのです。
#!perluse strict;use warnings;my $str = <<EOT;firstsecondthirdEOTfor my $re ( qr/^(.*?)$/, qr/^(.*?)$/m, qr/^(.*?)$/s, qr/^(.*?)$/ms ) { my $s = $str; print "\$re = $re\n"; $s =~ s{$re}{print "<$1>"}eg; print "\n";}
どうしてこうなってしまうかは宿題として(笑)この問題を抜本的に避けるための Best Practice が以下です。
^
ではなく\A
と指定する。$
ではなく\z
と指定する。ms
にしておく。.
は「改行をのぞく文字全種」ではなく、ただの「文字全種」となる。^
は「行頭」、$
は「行末」の意として使う。Perl best Practices に載っているものですが、フクロウ本によれば、Javaでも使えるはずの作法です。
困ったことに、JavaScriptはこれをフルサポートしていないのです。mはあってもsはなく、そのため.
が常に「改行を除く全文字」の意味にしかならない。仕方がないので[\s\S]
と書いています。
Dan the Regular Expressionist
naruseさん
今回の話は空白文字でなく制御文字をはじきたいんですよね。違いませんか。
そうか。ならば、話はもっと簡単だったりします。
[Run via codepad]#!perl -luse strict;use warnings;use utf8;sub check { $_[0] !~ /\p{C}/;}print 0+check("妥当な 文字列");print 0+check("妥当な 文字列"); # fullwidth spaceprint 0+check("妥当な\t文字列");print 0+check("妥当な 文字列\n");print 0+check("\x{00}\x{01}\x{02}\x{03}");
dankogai
Powered byライブドアブログ