Python中級プログラミング(1)
2023/10/22
何はともあれ正規表現
  • Python中級プログラミングでは「知っている」とプログラミングの自由度が上がるものを紹介していきます。最初は正規表現(Regular Expression)です。

  • 我々が扱うデータの多くは「テキスト...数値/文字列」です。このデータから情報を取り出す、または加工する等の処理が頻出します。よって楽にテキストを扱えればプログラミングの効率が上がります。

  • 記述が楽になると自然に多くの処理を重ねるようになり、その整理のために関数を使いたくなるという流れが生まれます。よって中級プログラミングとしては正規表現を起点にする方が良いと考えているわけです。

そもそも正規表現とは
  • プログラミングに馴染みがないと「正規表現」と言われてもピンと来ないでしょう。テキスト処理の強力なツールと理解して下さい。テキストの抽出/変換が簡単になります

  • 歴史的経緯(*1)から表現方法が独特なのは飲み込むしかありませんが、多くのプログラミング/スクリプト言語でも共通で使用できるため、正規表現は絶対に修得すべきと断言します。

正規表現の簡単な例(1)
  • 正規表現では条件(パターン)を与えて、文字列がパターンと一致(マッチ)するかを見ます。プログラミング言語によらず共通なのは条件(パターン)の記述方式で、本来はこれが正規表現と呼ばれるものです。

  • とりあえずPythonでの記述例を見てみましょう。正規表現を使用するためにreモジュールをインポートし、そこでsearchメソッドを使用します。青文字部が正規表現です。
  • import re
    
    str = "<li>  取り出したい 文字列   </li>"
    print("調査対象文字列: '", str, "'", sep="")
    
    o_m1 = re.search(r"<li>", str)
    if o_m1:
        print("マッチしました(1): '",str, "'", sep="")
    
    o_m2 = re.search(r"<li>\s*(\S.*\S)\s*</li>", str)
    if o_m2:
        print("マッチしました(2): '", o_m2.group(1), "'", sep="")
    
    調査対象文字列: '<li>  取り出したい 文字列   </li>'
    マッチしました(1): '<li>  取り出したい 文字列   </li>'
    マッチしました(2): '取り出したい 文字列'
    
  • 最初の
      o_m1 = re.search(r"<li>", str)
    では、"<li>" という文字列が含まれることがマッチ条件です

  • ここを "abc" とすれば "abc" を含む文字列がマッチ対象となります。特殊な記述ではありませんね。

  • しかし次の記述
      o_m2 = re.search(r"<li>\s*(\S.+\S)\s*</li>", str)
    は「ナニコレ?」ですよね。

  • これは「<li>〜</li>に囲まれ、前後にスペースがあればそれを除いた、文字列がある」(*2)ことをマッチ条件とする正規表現です。'取り出したい 文字列' の部分だけがきれいに引っ張り出せています。

  • あともう一点、正規表現を使用したパターンの文字列先頭には 'r' を付けています。
      o_m2 = re.search(r"<li>\s*(\S.+\S)\s*</li>", str)
    これはPythonのraw文字列というものです。エスケープ文字も「その文字自身」として解釈します。

  • 正規表現ではバックスラッシュ(\ 又は \)を多用するため、エスケープ文字と解釈させないようにraw文字列として記述するのが便利です。Windows系のファイルパスを扱う場合にもよく使いますね。

正規表現の簡単な例(2)
  • もう一つ例を見てみましょう。例えばログファイル等の文字列から数値を取り出す場合です。

  • 正負の数値/小数点の有無/単位を考慮してパターン
      re_pat = r"^\s*測定値(\d+)\s*:\s*([\+\-]*\d+\.*\d*)\s*(\D+)\s*$"
    を書いています。括弧()に囲まれた部分は3つで項目番号,測定値,単位に相当しています。多少スペースが入ったりしても抽出できるようにしています。
  • import re
    
    str1 = "測定値1: 100V"
    str2 = "測定値2 : -12.53 mV"
    re_pat = r"^\s*測定値(\d+)\s*:\s*([\+\-]*\d+\.*\d*)\s*(\D+)\s*$"
    
    o_m1 = re.search(re_pat, str1)
    print(o_m1.group(1),":",o_m1.group(2),"[",o_m1.group(3),"]")
    
    o_m2 = re.search(re_pat, str2)
    print(o_m2.group(1),":",o_m2.group(2),"[",o_m2.group(3),"]")
    
    1 : 100 [ V ]
    2 : -12.53 [ mV ]
    

正規表現記述のバリエーションは次回
  • さて、正規表現で何ができそうかイメージが湧いたでしょうか。正規表現修得のモチベーションが生まれたでしょうか。

  • 次回は正規表現を使いこなすために、そのコンポーネントを説明したいと思います。私自身もPython修得中なので「チートシート」(*3)となるように書くつもりです。
Notes
  • 我々おじさん世代だとsed→awk→Perlの流れで身につけるものでした。
  • この書き方だと2文字以上の制約があります。とりあえず全抽出してから前後のスペースを削ったほうが楽かも。
  • 気付くとPerlの書き方に。必要だ...チートシートが...!!
Copyright(C) 2023 Altmo
本HPについて