プロが教えるわが家の防犯対策術!

お世話になります。
正規表現の文字クラスについてお聞きします。

0~6 の数字1字を [0-6] という風に指定しますが、
.NET 正規表現では、
この中から 3~5 は除く、というようなとき、
[0-6-[3-5]] と言う風に書けるようですが、
Perl では書けないようです。
(一応ラクダ本と perldoc perlre には当たりました)

#! perl
# regtest.pl -- 正規表現のテスト

while(<DATA>) {
chomp;
print "$_ matches /[0-6-[3-5]/\n" if /[0-6-[3-4]/;
}

__DATA__
0
1
2
3
4
5
6
7
8
9

のようなスクリプトを動かすと、

C:\test>regtest.pl
0 matches /[0-6-[3-5]/
1 matches /[0-6-[3-5]/
2 matches /[0-6-[3-5]/
3 matches /[0-6-[3-5]/
4 matches /[0-6-[3-5]/
5 matches /[0-6-[3-5]/
6 matches /[0-6-[3-5]/

のような結果が得られ、引き算が確かに聞いていません。

Perl と .NET 正規表現は互換ではないのでしょうか。
また、Perl でも同じことが書けるでしょうか。
よろしくご教示願います。

A 回答 (3件)

.NET 正規表現とは違ったアプローチになりますが、一応あることはあります。


(.NET 正規表現互換も、package Something; use overload; sub import { overload::constant qr => \&substraction } sub substraction { #... } みたいなことをすればできるかもしれませんが――私はよく知りません)

本題に戻りますが、Unicode ブロック属性を用いれば目的は果たせると思います。
例えば:

use utf8;
print 1 if 'あ' =~ /\p{InHiragana}/;

このように、\p{InHOGE} という形の文字クラス (と呼ぶのでしょうか) が utf8 プラグマの機能として (自信なし) 用意されています。
ちなみに、CJK 統合漢字の属性は \p{InCJKUnifiedIdeographs} だったと思います。
さらにこの属性を自分で作ることもでき:

sub InKana {
return <<'EOF';
+utf8::InHiragana
+utf8::InKatakana
EOF
}

まあこんな感じで、+ から始まる属性は追加、- から始まるやつは削除という風に定義できるらしいです。
応用すれば CJK から J を引いたクラスも作れると思います。
文字のバイト列を調べて平仮名かどうか調べる――といったテクニックの現代版と言えるのでしょうか。分かりません。

`perldoc perlunicode' で more details を得ることができると思います。
なお、この回答は全般的に「自信なし」です。

この回答への補足

下のお礼の続きです。
文字プロパティが定義できることは知ってたんですが、マイナスで削除できるところは知りませんでした。
ややこしいですが便利ですね。
本当にありがとうございます。

補足日時:2008/10/21 17:13
    • good
    • 0
この回答へのお礼

ありましたね、文字プロパティのユーザー定義!
これで行けると思います。

#! perl
# regtest.pl -- 正規表現のテスト

while(<DATA>) {
chomp;
print "$_ matches /\\p\{p01256\}/\n" if /\p{p01256}/;
}

sub p01256 {
return<<'EOF';
+0030 0036
-0033 0034
EOF
}

__DATA__
0
1
2
3
4
5
6
7
8
9

=>

0 matches /\p{p01256}/
1 matches /\p{p01256}/
2 matches /\p{p01256}/
5 matches /\p{p01256}/
6 matches /\p{p01256}/

でバッチリです。
どうもありがとうございます!

お礼日時:2008/10/21 17:12

0~2と6なら [0-26] と書きます。



> Perl が機能の豊富さで他の言語に負けるのはめずらしいケースなので、

そもそも、Perlは正規表現を実装している言語の中では古い方です。
現在、正規表現に対応している言語の大半はPerlの正規表現を参考に
作られています。
(そのため、Perlの正規表現互換の記述である場合が多いです)

一方で、古いために新しい要求などがでてきても仕様が古いために
対応されていません。
新しい言語ではその辺を独自に改良している場合があります。

しかし、お書きになっているような書き方よりPerlのような書き方の
方がずっと簡単でシンプルだと思いますが...。
    • good
    • 0
この回答へのお礼

ありがとうございます。
たぶん見方が違うんだと思うんですが、Perl の正規表現はだらしないほど拡張しまくっているように思えます。
たとえば (?<=PATTERN) のような文字を消費しないパターンとか、パターンを再帰させてカッコの対応にマッチさせるようなのは、昔なかったような? 気がします。
とまれ、確かに、上の書き方はシンプルではありませんね。
状況を説明すると、.NET と Perl で同じ処理を書いていて、.NET で書いた人がくれたパターンが Perl で動かなかったという感じです。
マーその作業の体制が???という話はあるんですが・・・(^^;

お礼日時:2008/10/21 17:11

perlではそのような記述はしないと思いますが



[0126789]という書き方ではダメなのですか?
(質問の趣旨とずれていたらすみません)

この回答への補足

ありがとうございます。
たとえば「CJK統合漢字全体から日本語で使う漢字を除いた残り」
(日本では使わない漢字)
と言う風に、上の 0-9 にあたる文字セットも
3-5 に当たる文字セットも膨大なケースを想定しています。
Perl が機能の豊富さで他の言語に負けるのはめずらしいケースなので、
質問しました。。。

補足日時:2008/10/21 13:13
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!