2016-04-29 15 views
4

このような簡単な質問は申し訳ありませんが、私はまだ経験の浅いプログラマです。私は職場でいくつかの古いperlコードの電話番号一致の正規表現を見つけました。誰かがそれが何を意味するのかを正確に説明できるなら、私はそれを気に入っています(私の正規表現のスキルには深刻な欠点があります)。 Perlの電話番号の正規表現

if ($value !~ /^\+[[:space:]]*[0-9][0-9.[:space:]-]*(\([0-9.[:space:]-]*[0-9][0-9.[:space:]-]*\))?([0-9.[:space:]-]*[0-9][0-9.[:space:]-]*)?([[:space:]]+ext.[0-9.[:space:]-]*[0-9][0-9.[:space:]-]*)?$/i) { 
    ... 
} 

は、事前にありがとう:)

答えて

9

コードは大体 "あなたはNumber::Phoneでこれを置き換える必要があります" と言います。

すべての冗談と良い助言を除いて、正規表現を計算するときにまず最初に行うことは/xで展開することです。最初のパスは、キャプチャグループによって物事を壊すことです。

/^ 
\+[[:space:]]*[0-9][0-9.[:space:]-]* 
(\([0-9.[:space:]-]*[0-9][0-9.[:space:]-]*\))? 
([0-9.[:space:]-]*[0-9][0-9.[:space:]-]*)? 
([[:space:]]+ext.[0-9.[:space:]-]*[0-9][0-9.[:space:]-]*)? 
$/xi 

次に、これは文字セットによって支配されているため、私は文字セットごとにスペースをとっていました。

/^ 
\+ [[:space:]]* [0-9] [0-9.[:space:]-]* 
(\([0-9.[:space:]-]* [0-9] [0-9.[:space:]-]* \))? 
([0-9.[:space:]-]* [0-9] [0-9.[:space:]-]*)? 
([[:space:]]+ ext . [0-9.[:space:]-]* [0-9] [0-9.[:space:]-]*)? 
$/xi 

これで、同様の要素が表示されるようになりました。それらを並べて、類似点を見てみてください。

/^ 
\+  [[:space:]]* [0-9] [0-9.[:space:]-]* 
(\([0-9.[:space:]-]* [0-9] [0-9.[:space:]-]* \))? 
( [0-9.[:space:]-]* [0-9] [0-9.[:space:]-]* )? 
([[:space:]]+ 
    ext . 
     [0-9.[:space:]-]* [0-9] [0-9.[:space:]-]* 
)? 
$/xi 

次に、要素をゼロにしてそれを試してみてください。これは重要なもので、[0-9.[:space:]-]*を意味します。「0以上の数字、スペース、ダッシュまたはドット」を意味します。それは電話の解析にはあまり意味がありません。多分、それは文脈の中でより意味をなさないでしょう。私たちはそれがしようとしていると推測できる行を見てみましょう。

(\([0-9.[:space:]-]* [0-9] [0-9.[:space:]-]* \))? 
  • 開きかっこ。
  • ゼロ以上の数字、スペース、ダッシュまたはドット。
  • 番号
  • ゼロ以上の数字、スペース、ダッシュまたはドット。
  • 閉じる。

これは、市外局番を解析しようとしていることを示しています。残りの数字は任意の数の数字、スペース、ダッシュまたはドットに制限されますが、[0-9]は確実に少なくとも1つの番号があります。これは、多数の電話番号形式を扱う作者の方法でしょう。

著者に電話番号が決まったと判断したので、名前を付けてみましょう。phone_charsとしましょう。別の要素、[0-9.[:space:]-]* [0-9] [0-9.[:space:]-]*があります。これは、電話番号のアトムを作者が決定したため、「電話アトム」と呼ばれます。それを独自の正規表現に入れてそれと電話機の正規表現を構築すれば、物事ははっきりと分かります。

my $phone_chars = qr{[0-9.[:space:]-]}; 
my $phone_atom = qr{$phone_chars* [0-9] $phone_chars*}x; 

/^ 
\+ [[:space:]]* [0-9] $phone_chars* 
(\($phone_atom \))? 
( $phone_atom )? 
([[:space:]]+ ext . $phone_atom)? 
$/xi; 

あなたが電話番号について何かを知っていれば、それはこのようなものだ:

  1. (+と数字で始める必要があります)必須の国コード
  2. オプションのエリアコード
  3. オプションの電話番号
  4. オプションの内線番号

この正規表現は電話番号を検証するうまくいっていません。この正規表現によれば、 "+1"は有効な電話番号ですが、 "(555)123-4567"は国番号がないためではありません。

電話番号の検証は難しいです。私はNumber::Phoneを言及しましたか?少し空白やいくつかのコメントを行うことができ、拡張どのようなモード、

use strict; 
use warnings; 
use v5.10; 

use Number::Phone; 

my $number = Number::Phone->new("+1(555)456-2398"); 
say $number->is_valid; 
+1

あなたは驚くべきものです。ありがとうございます:) – Jordan

+1

男、あなたは速いです! :-) – Marty

6

アメイジング...

if ($value !~/
    ^    # Anchor to start of string 

    \+     # followed (immediately) by literal '+' 
    [[:space:]]*  # zero or more chars in the POSIX character class 'space' 
    [0-9]    # compolsory digit 
    [0-9.[:space:]-]* # zero or more digit, full-stop, space or hyphen 

    (     # start capture to $1 
     \(     # Literal open parentheses 
     [0-9.[:space:]-]* # zero or more ... (as above) 
     [0-9]    # compolsory digit 
     [0-9.[:space:]-]* # zero or more ... (as above) 
     \)     # Literal close parentheses 
    )?     # close capture to $1 - whole thing optional 

    (     # start capture to $2 
     [0-9.[:space:]-]* # zero or more ... (as above) 
     [0-9]    # compolsory digit 
     [0-9.[:space:]-]* # zero or more ... (as above) 
    )?     # close capture to $2 - whole thing optional 

    (     # start capture to $3 
     [[:space:]]+   # at least one space (as definned by POSIX) 
     ext.     # literal 'ext' followed by any character 
     [0-9.[:space:]-]* # zero or more ... (as above) 
     [0-9]    # compolsory digit 
     [0-9.[:space:]-]* # zero or more ... (as above) 
    )?     # close capture to $3 - whole thing optional 

     $     # Anchor to end of string 
       /ix  # close regex; ignore case, extended mode options 
    ) { 
+0

ありがとうMarty :) – Jordan

関連する問題