┌───────┐
│perl超入門(3) │
│  2002/10/27 │
└───────┘

[▲Perl Home▲]

パターンマッチ

 マッチ演算子
 
  ・マッチ演算子「/指定文字列/」 によりデータが指定文字列を含むか否かをチェック。
  ・マッチ対象にはメタ文字(\n, \a, \t)も含まれる。

  ・特別な(マッチ/正規表現上特別な意味を持つ)文字にはエスケープ表記(\記号を付
   ける)を適用
する。(例は示さない)
     . : \.
     \ : \\
     * : \*
     ? : \?
     | : \|
     + : \+
     ^ : \^
  ・機種により\記号はバックスラッシュになる。

 ┌─────────────────────────────────────┐
  while (<>) {
    if (/abc/) {
      print "○ ", $_;
    } else {
      print "× ", $_;
    }
  }
 └─────────────────────────────────────┘
 ┌─────────────────────────────────────┐
  [data.txt]
  ┌───────┐
  │abc:001    │
  │ABC:002    │
  │abcdefg:004  │
  │ABCDEFG:005  │
  │012abcdefg:006│
  │012ABCDEFG:007│
  └───────┘
  
  C:> jperl test.pl data.txt
  ○ abc:001
  × ABC:002
  ○ abcdefg:004
  × ABCDEFG:005
  ○ 012abcdefg:006
  × 012ABCDEFG:007
 └─────────────────────────────────────┘
 
  ・大文字と小文字を区別させないオプション「/指定文字列/i」。

 ┌─────────────────────────────────────┐
  while (<>) {
    if (/abc/i) {
      print "○ ", $_;
    } else {
      print "× ", $_;
    }
  }
 └─────────────────────────────────────┘
 ┌─────────────────────────────────────┐
  [data.txt] ← 前の例と同じ
  
  C:> jperl test.pl data.txt
  ○ abc:001
  ○ ABC:002
  ○ abcdefg:004
  ○ ABCDEFG:005
  ○ 012abcdefg:006
  ○ 012ABCDEFG:007
 └─────────────────────────────────────┘

 
 パターン結合演算子

  ・マッチ対象を変数と結び付けるには、パターン結合演算子「=~」を使用。

 ┌─────────────────────────────────────┐
  @datas = ( 'abc:001',
        'ABC:002',
        'abcdefg:004',
        'ABCDEFG:005',
        '012abcdefg:006',
        '012ABCDEFG:007' );
       
  foreach $tmp (@datas) {
    if ($tmp =~ /abc/) {
      print "○ ", $tmp, "\n";
    } else {
      print "× ", $tmp, "\n";
    }
  }
 └─────────────────────────────────────┘
 ┌─────────────────────────────────────┐
  ○ abc:001
  × ABC:002
  ○ abcdefg:004
  × ABCDEFG:005
  ○ 012abcdefg:006
  × 012ABCDEFG:007
 └─────────────────────────────────────┘


 アンマッチ
 
  ・マッチしないことはパターン結合演算子の一つである「!~」で表す

 ┌─────────────────────────────────────┐
  @datas = ( 'abc:001',
        'ABC:002',
        'abcdefg:004',
        'ABCDEFG:005',
        '012abcdefg:006',
        '012ABCDEFG:007' );
       
  foreach $tmp (@datas) {
    if ($tmp !~ /abc/) {
      print "○ ", $tmp, "\n";
    } else {
      print "× ", $tmp, "\n";
    }
  }
 └─────────────────────────────────────┘
 ┌─────────────────────────────────────┐
  × abc:001
  ○ ABC:002
  × abcdefg:004
  ○ ABCDEFG:005
  × 012abcdefg:006
  ○ 012ABCDEFG:007
 └─────────────────────────────────────┘
 
  ・否定は結合演算子で表すので、$_の省略に対しては否定表現が無い。この場合は省
   略しないで記述
する。
   
     if ($_ !~ /abc/) {
      :
     }


 マッチ演算子の文字変更
 
  ・マッチ対象文字列に「/」を含んでいる場合、マッチ演算子の文字を変更する。
     mマッチ演算子文字 → m#/abc#
                m%/abc% 等々...
     
 ┌─────────────────────────────────────┐
  @datas = ( '/abc:001',    #検索対象1
        'ABC:002',
        'abcdefg:004',
        'ABCDEFG:005',
        '012/abcdefg:006', #検索対象2
        '012ABCDEFG:007' );
       
  foreach $tmp (@datas) {
    if ($tmp =~ m#/abc#) {
      print "○ ", $tmp, "\n";
    } else {
      print "× ", $tmp, "\n";
    }
  }
 └─────────────────────────────────────┘
 ┌─────────────────────────────────────┐
  ○ /abc:001
  × ABC:002
  × abcdefg:004
  × ABCDEFG:005
  ○ 012/abcdefg:006
  × 012ABCDEFG:007
 └─────────────────────────────────────┘


正規表現

 行頭/行末
 
  ・文字列中に意味のあるメタ文字を適用することが出来る:正規表現
  
  ・行頭/行末の表現
    ^ : 行頭
    $ : 行末
    \Z : \n行末 ← chop()されていない変数等に適用
            \n(改行)をエスケープする

 ┌─────────────────────────────────────┐
  while (<>) {
    if (/^abc/) {
      print "○ ", $_;
    } else if (/6\Z/){
      print "△ ", $_;
    } else {
      print "× ", $_;
    }
  }
 └─────────────────────────────────────┘
 ┌─────────────────────────────────────┐
  [data.txt]
  ┌───────┐
  │abc:001    │
  │ABC:002    │
  │abcdefg:004  │
  │ABCDEFG:005  │
  │012abcdefg:006│
  │012ABCDEFG:007│
  └───────┘
  
  C:> jperl test.pl data.txt
  ○ abc:001
  × ABC:002
  ○ abcdefg:004
  × ABCDEFG:005
  △ 012abcdefg:006
  × 012ABCDEFG:007
 └─────────────────────────────────────┘


 数字/数字以外 : (半角)
 
   \d : 数字1文字
   \D : 数字以外1文字

 ┌─────────────────────────────────────┐
  @datas = ( 'abc:001',
        'ABC:002',
        'Gabcdefg:004',
        'SABCDEFG:005',
        '012abcdefg:006',
        '012ABCDEFG:007' );
       
  foreach $tmp (@datas) {
    if ($tmp =~ /\dabc/) {
      print "○ ", $tmp, "\n";
    } elsif ($tmp =~ /\Dabc/) {
      print "△ ", $tmp, "\n";
    } else {
      print "× ", $tmp, "\n";
    }
  }
 └─────────────────────────────────────┘
 ┌─────────────────────────────────────┐
  × abc:001
  × ABC:002
  △ Gabcdefg:004
  × SABCDEFG:005
  ○ 012abcdefg:006
  × 012ABCDEFG:007
 └─────────────────────────────────────┘


 英数字/英数字以外 : (半角)
 
   \w : 英数字1文字
   \W : 英数字以外1文字 (@, :, ; 等の記号とマッチ)
   (注)_(アンダーバー)は英文字扱いとなる

 ┌─────────────────────────────────────┐
  @datas = ( 'abc001',
        'ABC002',
        'Gabc:defg003',
        'Gabc_defg004',
        'SGABCDEFG005' );
       
  foreach $tmp (@datas) {
    if ($tmp =~ /abc\w/) {
      print "○ ", $tmp, "\n";
    } elsif ($tmp =~ /abc\W/) {
      print "△ ", $tmp, "\n";
    } else {
      print "× ", $tmp, "\n";
    }
  }
 └─────────────────────────────────────┘
 ┌─────────────────────────────────────┐
  ○ abc001
  × ABC002
  △ Gabc:defg003
  ○ Gabc_defg004
  × SGABCDEFG005
 └─────────────────────────────────────┘


 空白/空白以外 : (半角)
 
   \s : 空白1文字
   \S : 空白以外1文字

 ┌─────────────────────────────────────┐
  @datas = ( 'abc 001',
        'abc_002',
        'defg 003',
        'defg004' );
       
  foreach $tmp (@datas) {
    if ($tmp =~ /abc\s/) {
      print "○ ", $tmp, "\n";
    } elsif ($tmp =~ /\s/) {
      print "△ ", $tmp, "\n";
    } else {
      print "× ", $tmp, "\n";
    }
  }
 └─────────────────────────────────────┘
 ┌─────────────────────────────────────┐
  ○ abc 001
  × abc_002
  △ defg 003
  × defg004
 └─────────────────────────────────────┘


 任意の1文字
 
   . : 任意の1文字と一致

 ┌─────────────────────────────────────┐
  @datas = ( 'abc',
        'abc0',
        'def1',
        'abc2' );
       
  foreach $tmp (@datas) {
    if ($tmp =~ /abc./) {
      print "○ ", $tmp, "\n";
    } else {
      print "× ", $tmp, "\n";
    }
  }
 └─────────────────────────────────────┘
 ┌─────────────────────────────────────┐
  × abc
  ○ abc0
  × def1
  ○ abc2
 └─────────────────────────────────────┘


 文字クラス
 
   [文字A文字B・・・] (例)[ABC] : A or B or Cに一致
   [^文字A文字B・・ ] (例)[^ABC] : A or B or C以外に一致
   
   「-」で範囲指定もできる
     (応用例) [a-c0-2] : a/b/c又は0/1/2に一致
          [a-zA-Z] : 全てのアルファベットに一致
          [0-9]  : 全ての数字に一致
          [ぁ-ん] : 全てのひらがなに一致

 ┌─────────────────────────────────────┐
  @datas = ( 'abc',
        'abC0',
        'def1',
        'abC2',
        'abC3',
        'abC4' );
       
  foreach $tmp (@datas) {
    if ($tmp =~ /[0c]/) {
      print "○ ", $tmp, "\n";
    } elsif ($tmp =~ /C[^1-3]/) {
      print "△ ", $tmp, "\n";
    } else {
      print "× ", $tmp, "\n";
    }
  }
 └─────────────────────────────────────┘
 ┌─────────────────────────────────────┐
  ○ abc
  ○ abC0
  × def1
  × abC2
  × abC3
  △ abC4
 └─────────────────────────────────────┘


 連続文字
 
   ※このセクション以降、「文字」は「文字クラス」も含む。
   
   文字*   : 文字が連続で0個以上に一致
   文字+   : 文字が連続で1個以上に一致
   文字?   : 文字が0個or1個あるパターンに一致
   
   文字{数1}   : 文字が連続で「数1」個あるパターンに一致
   文字{数1,}  : 文字が連続で「数値以上」個あるパターンに一致
   文字{数1,数2} : 文字が連続で「数1以上,数2以下」個あるパターンに一致

 ┌─────────────────────────────────────┐
  @datas = ( 'abc',
        'abc0',
        'abc00',
        'abc000',
        'abc0000',
        'abc0def0',
        'abc00000',
        'abc00000a',
        'abc000000',
        'def0000000' );
  
  print "1 2 3 4 5 6\n";
 
  foreach $tmp (@datas) {
    if ($tmp =~ /abc0*/) { print '* ' }     #条件1
    else { print '. ' }
    
    if ($tmp =~ /abc0+/) { print '* ' }     #条件2
    else { print '. ' }
    
    if ($tmp =~ /abc0?[a-zA-Z]/) { print '* ' } #条件3
    else { print '. ' }
    
    if ($tmp =~ /abc0{3}$/) { print '* ' }   #条件4
    else { print '. ' }
    
    if ($tmp =~ /abc0{3,}$/) { print '* ' }   #条件5
    else { print '. ' }
    
    if ($tmp =~ /abc0{3,5}$/) { print '* ' }  #条件6
    else { print '. ' }
    
    print "$tmp\n";
  }
 └─────────────────────────────────────┘
 ┌─────────────────────────────────────┐
  1 2 3 4 5 6
  * . . . . . abc
  * * . . . . abc0
  * * . . . . abc00
  * * . * * * abc000
  * * . . * * abc0000
  * * * . . . abc0def0
  * * . . * * abc00000
  * * . . . . abc00000a
  * * . . * . abc000000
  . . . . . . def0000000
 └─────────────────────────────────────┘


 選択
 
   文字列A | 文字列B : 文字列A or 文字列Bが含まれる

 ┌─────────────────────────────────────┐
  @datas = ( 'abc',
        'def',
        'ghi',
        'abcghi',
        'ghidef',
        'jkl'
       );
  
  foreach $tmp (@datas) {
    if ($tmp =~ /abc|def/) {
       print "○ ",$tmp,"\n";
    } else {
       print "× ",$tmp,"\n";
    }
  }
 └─────────────────────────────────────┘
 ┌─────────────────────────────────────┐
  ○ abc
  ○ def
  × ghi
  ○ abcghi
  ○ ghidef
  × jkl
 └─────────────────────────────────────┘


 単語の境界
 
   \b : 境界文字(非英数字)なら一致
   \B : 非境界文字(英数字)なら一致
     
     ↓ 実質的には以下のように使用することが多い
     
   \b文字列\b : 文字列の前後が英文字以外(独立単語)なら一致
   \B文字列\B : 指定文字列がある文字列の一部(独立していない)なら一致

 ┌─────────────────────────────────────┐
  @datas = ( '私の名前はmonpeです',
        '私の名前はmonpe2です',
        'メールアドレスがmonpe@mail.jp (うそ)',
        'Webmastermonperoom',
        '全くの意味無し文字列',
        'Webmaster monpe room'
       );
  
  foreach $tmp (@datas) {
    if ($tmp =~ /\bmonpe\b/) {
       print "○ ",$tmp,"\n";
    } elsif ($tmp =~ /\Bmonpe\B/) {
       print "△ ",$tmp,"\n";
    } else {
       print "× ",$tmp,"\n";
    }
  }
 └─────────────────────────────────────┘
 ┌─────────────────────────────────────┐
  ○ 私の名前はmonpeです
  × 私の名前はmonpe2です
  ○ メールアドレスがmonpe@mail.jp (うそ)
  △ Webmastermonperoom
  × 全くの意味無し文字列
  ○ Webmaster monpe room
 └─────────────────────────────────────┘


 後方参照
 
  ・既出の文字列を表現する。(パターン指定文字列内のみ)
  
    (文字列a) 文字列 (文字列b) 文字列 \1 文字列 \2 文字列
     ここで
      \1 : 文字列a
      \2 : 文字列b
     を表す。\の後の数値は必要分付けられる。

 ┌─────────────────────────────────────┐
  @datas = ( 'abcdefghi abcjklmn',
        'abcdefghi jklmnopq'
       );
  
  foreach $tmp (@datas) {
    if ($tmp =~ /(abc)defghi \1/) {
       print "○ ",$tmp,"\n";
    } else {
       print "× ",$tmp,"\n";
    }
  }
 └─────────────────────────────────────┘
 ┌─────────────────────────────────────┐
  ○ abcdefghi abcjklmn
  × abcdefghi jklmnopq
 └─────────────────────────────────────┘


 マッチ文字列の利用
 
  ・マッチした部分文字列を利用する
  
    (マッチ文字列1) 文字列 (マッチ文字列2) 文字列
      $1 : マッチ文字列1
      $2 : マッチ文字列2

 ┌─────────────────────────────────────┐
  @datas = ( '品物A 価格 \1000 //備考1',
        '品物B 価格 \2000',
        '品物C 価格 \3000 //備考2',
        '品物D 価格 \4000'
       );
  
  foreach $tmp (@datas) {
    if ($tmp =~ /(品物\w) 価格 (\\\d+)/) {
       print $1," : ",$2,"\n";
    }
  }
 └─────────────────────────────────────┘
 ┌─────────────────────────────────────┐
  品物A : \1000
  品物B : \2000
  品物C : \3000
  品物D : \4000
 └─────────────────────────────────────┘

以上

[▲Perl Home▲]