• ベストアンサー

正規表現を教えて下さい

「2つ目のドット"."までに、1つのドットと8文字以上の数字を含む」という正規表現で悩んでいます。 正規表現が得意な方、ヒントを頂ければ助かります。

質問者が選んだベストアンサー

  • ベストアンサー
  • moon_piyo
  • ベストアンサー率60% (88/146)
回答No.7

プログラムがつかえない場所だとすると... こんなのはどうでしょう わかりやすいように正規表現に改行をいれて xオプションをつけていますけど、xオプションが許されないようでしたら改行を削って長い一行にしてください /( [^\.\d]*(\d[^\.\d]*){0,}\.[^\.\d]*(\d[^\.\d]*){8,}| [^\.\d]*(\d[^\.\d]*){1,}\.[^\.\d]*(\d[^\.\d]*){7,}| [^\.\d]*(\d[^\.\d]*){2,}\.[^\.\d]*(\d[^\.\d]*){6,}| [^\.\d]*(\d[^\.\d]*){3,}\.[^\.\d]*(\d[^\.\d]*){5,}| [^\.\d]*(\d[^\.\d]*){4,}\.[^\.\d]*(\d[^\.\d]*){4,}| [^\.\d]*(\d[^\.\d]*){5,}\.[^\.\d]*(\d[^\.\d]*){3,}| [^\.\d]*(\d[^\.\d]*){6,}\.[^\.\d]*(\d[^\.\d]*){2,}| [^\.\d]*(\d[^\.\d]*){7,}\.[^\.\d]*(\d[^\.\d]*){1,}| [^\.\d]*(\d[^\.\d]*){8,}\.[^\.\d]*(\d[^\.\d]*){0,} )\./x; "0コ以上の数字 . 8コ以上の数字 ." または "1コ以上の数字 . 7コ以上の数字 ." または .... "8コ以上の数字 . 0コ以上の数字 ." という作戦でやってみました

10gate
質問者

お礼

結果報告です。 No.6で教えて頂いた方法と、No.7の方法はperlでは全く同じ結果となりました。しかもこちらの期待通りの結果です。驚きました・・。 今回はNo.7の方法を採用させて頂きました。 正規表現は奥深いです。絶対不可能と思えたのですが、知恵が足りなかったです。 今回締め切らせて頂きますが、たくさんのアイデアを頂いた各回答にポイントを付けられなくて申し訳ありません。 ご回答頂いた皆様、ありがとうございました。

その他の回答 (6)

  • moon_piyo
  • ベストアンサー率60% (88/146)
回答No.6

(?{code}) (?(condition)yes|no) などの正規表現が使えるPerlでしたら /(\d(?{local $n_d=$n_d+1})|\.(?{local $n_p=$n_p+1})|[^\d\.])*\.(?(?{!($n_d >= 8 && $n_p == 1)})(?!))/; というのはどですか \dにマッチするごとに $n_d++ \.にマッチするごとに $n_p++ \.にマッチしたときに $n_d >= 8 && $n_p == 1 の条件を満たさなければ次を探す という動きになります

10gate
質問者

お礼

こんな無茶な質問に真摯に答えて下さってありがとうございます。 下でも書かせて頂いたのですが、正規表現はperlと同じなのですが、perlで使うわけではなく・・。紛らわしくて申し訳ありません。 ただご指摘頂いた表現が使えるかどうか明日試してみたいと思います(確かperl5.8互換だったように記憶していますが・・)。 結果は明日ご報告致します。

  • moon_night
  • ベストアンサー率32% (598/1831)
回答No.5

正規表現一回だけではできそうもなかったので、 違う手で処理してみました。 参項程度に。 @aaa = ( '111.abc222.何か文字列', 'abc12.111-222ddd.何か文字列', '..', '.12345678.', '12345678.aaa.task', '5231.asd123.123da543123455', 'ab123-45.6-7891.aa', 'asd123.1234asd567', '88ii88.88ii88ii88', ); foreach (@aaa) { @words = split(//); $end = 0; $kaz = 0; foreach $words (@words) { if ($words eq '.') { $end++; } elsif ($words =~ /\d/) { $kaz++; } if ($end >= 2) { last; } } if ($end == 2 and $kaz >= 8) { print "HIT!\n"; } else { print "NG\n"; } }

10gate
質問者

お礼

何度もありがとうございます。 No.4様のお礼でも記載したのですが、perlと同じ正規表現なのですが、実際にはプログラムを使えない場所で使うため、一回で表現する必要がございまして・・ perlのカテゴリで質問してしまってすみません。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.4

先ほどは失礼しました。 要件は 1.2つ以上のピリオドがあること 2.かつ2つ目のピリオドの前に8つ以上の数字(非連続可)があること ですね。 2回の検索をかければできますが、1回では無理なようです。 以下、2回で行う方法。 $strが検索対象の文字列 #最短一致でピリオドが2つ以上のケースを抽出し if ( $str =~ /(.*?)\.(.*?)\./ ){ #更に、2番目のピリオドまでに8個以上の数字があること if ( ($1.$2) =~ /(\d.*){8,}/ ){ # マッチしたケース print "match\n"; } }

10gate
質問者

お礼

お礼が遅くなってすみません。 > 2.かつ2つ目のピリオドの前に8つ以上の数字(非連続可)があること > ですね。 はい、その通りです。 > 2回の検索をかければできますが、1回では無理なようです。 そうですよね・・ 私もさんざん考えたのですが、分裂した数字の合計個数が8つ以上なんて無理かなと思います。 一応今まで考えたのは /^[^\.0-9]*[0-9]+\.[^\.0-9]*[0-9]+\./ こんな感じなのですが・・。 それと、実際にこの表現を使うのが、perlではなく別のプログラムなのですが、2回に分ける事ができないのです。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.3

>2つ目のピリオドまでに、数字が8文字どこかに入っ>てるのも条件なのです・・ 質問 1)ピリオドとピリオドの間に、数字は何文字以上あれば、よいのですか?  1.8文字ちょうど  2.1~8文字  3.8文字以上なら何文字でも良い 2)数字と数字の間は、ピリオド以外の文字があっても よいのですね。 3)以下の形はOKですかNGですか aa.ab1k1k1k1k1k1k1k1.+++ aa.1.yyy aa.1111111hh111111+1hh111.zzz

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.2

要は、ピリオド+ピリオド以外の文字(0文字以上)+ピリオド が検索できればよいのですね。 $str =~ /\.[^.]*\./ になります。 以下のスクリプトで確認してみて下さい。 -------------------------------- $a = "mmm.123-46.lll"; $b = ".."; $c = "jj.llll"; &sub1 ($a); &sub1 ($b); &sub1 ($c); sub sub1 { $str = shift @_; if ( $str =~ /\.[^.]*\./ ){ print $str ," is match\n"; }else{ print $str ," is not match\n"; } }

10gate
質問者

お礼

ご回答ありがとうございます。 2つ目のピリオドまでに、数字が8文字どこかに入ってるのも条件なのです・・

  • moon_night
  • ベストアンサー率32% (598/1831)
回答No.1

別に正規表現は得意ではありませんが。 $word =~ /\.\d{8,}\./ig; こんなかんじなのでは。 ただし、これでは数字以外の文字が挟まっていた場合にはHITしませんが。 数字以外が挟まっている場合がある場合は $word =~ /\.\D*\d+\D*\d+\D*\d+\D*\d+\D*\d+\D*\d+\D*\d+\D*\d+\D*\./ig; こんな感じでいけるのかなぁ? (試してないのでビミョウ) もっとうまい手があると思います。

10gate
質問者

お礼

早速のご返答ありがとうございます。 すみません、最初の質問があいまいだったのですが、 ドットとドットの間に数字が8文字以上ではなく、例えば以下のような文字列です。 111.abc222.何か文字列 abc12.111-222ddd.何か文字列 とか。 正直不可能かとも思っていますが・・

10gate
質問者

補足

すみません、お礼のところで間違いがありました。 111.abc222.何か文字列 では数字が6文字でした。 111.abc222dd33.何か文字列 とかです。

関連するQ&A