正規表現の後読み

(※注意)この記事は博士とロボの会話文が入っています。

次の表のように文字列を抽出したいとします。

No文字列抽出する文字列
12009年12月23日気温11℃11℃
22009年12月24日気温12℃12℃
32009年12月25日気温13℃13℃
42009年12月26日気温14℃14℃
52009年12月27日気温15℃15℃
62009年12月28日気温16℃16℃
最初にこんな形で取得したとします。

[regex]::match( 文字列 , "11℃|12℃|13℃|14℃|15℃|16℃" )

( 博士 )「17℃のときはどうするんだ?」
( ロボ )「メンゴメンゴ。|17℃を追加いたしやす。」
( 博士 )「そうじゃなくて、これじゃひっかからないものもあるだろう?」
( ロボ )「…」
( ロボ )「…!!」
生たまごを博士に投げるロボ
( 博士 )(クチャ)「うっ…」
( ロボ )「アハハーwwwハハ」

これでは、マイナスや17℃以上には対応出来ないので次のようにします。

[regex]::match( 文字列 , "-*\d+℃" )

正規表現で「*」は直前の文字の0回以上の繰り返し(ワイルドカードとは異なります)、「\d」は数値、「+」は直前の文字の1回以上の繰り返しです。これでちゃんと取得できると思われます。しかし「℃」ではなく「度」となっていた場合や「℃」がない場合はどうすればよいのでしょう?(むりやり) その際、PowerShellでは後読みが使えます。後読みは、直前にある文字列を条件に加えることが出来ます。今回の場合は「気温」を条件として、その後の文字列(11℃、12℃…)を取得できます。

[regex]::match( 文字列 ,"(?<=気温).*")

先読みもあります。先読みは直後にある文字列を条件に加えることが出来ます。

  • 先読み…<マッチさせたい文字列>(?=pattern)
  • 後読み…(?<=pattern)<マッチさせたい文字列>

以上を用いて、テキストファイルから指定した文字列の後にくる文字列を表示させるプログラムを作成しました。

set-PSDebug -strict
# ---------------------------
# テキストファイルから指定した文字列の後にくる文字列を表示
# 第一引数:取得文字列の前の文字列
# 第二引数:ファイルパス
# ---------------------------
function GetPositiveLookBehind{
    # 引数の取得
    param([string]$ahead_str,[string]$file_path)
    
    # テキスト取得
    $text = get-Content $file_path
    
    # 検索結果を配列で取得
    $result_array=@()
    foreach ( $line in $text ){
        # 肯定後読みパターンを編集
        $pattern = "(?<=$ahead_str).*"
        
        # 検索結果取得
        $result_array += [regex]::match($line,$pattern)
    }
    
    # 検索結果を画面に出力
    $count = 0  # カウンタ初期化
    foreach ( $result in $result_array ) {
        # 検索結果が成功の場合
        if ($result.Success){
            # 検索結果を出力
            write-Host $result.value
            $count += 1
        }
    }    
    # カウンタ数をを画面に出力
    $count_line = "★" + $count + "件マッチしました。"
    write-Host $count_line
}

以下実行結果です。