Postfix の送信エラーログを1件ずつ抽出して1ファイルに収めて、そこから対象メールアドレスを抽出し、それをキーにして顧客 csv ファイルを1行抽出するという面倒くさい作業がある。だもので、ファイルに収められた情報と csv ファイルの情報を突合して1行抜き出すことにした。環境は、Windows10 の Ubuntu 18 で行った。

 

まず、特定のディレクトリにログファイルを全て納めてスタート。のっけからロケールが ja_JP.UTF-8 では無かったので設定。続いて、ファイルからメールアドレスを抽出。こんな感じ。シェルは bash を使用。nkf は仕方なくインストールした。iconv では正常動作しないため。

 

LANG=ja_JP.UTF-8
filenum=$(ls -p -U1 /mnt/c/workspace/Mail_1 | grep -v ./);
filename=()
filename+=($filenum)

for filename in "${filename[@]}"
do
    cat /mnt/c/workspace/Mail_1/$filename | awk '/The mail system/,/Content/' > TEMP2.txt
        grep -o "[-_a-zA-Z0-9\.]*@[-a-zA-Z0-9\.]*" TEMP2.txt | uniq | awk '{print  >> "TEMP4.txt"}'
    if grep -o "RCPT" TEMP2.txt > /dev/null
        then
            awk 'BEGIN {print "in reply to RCPT TO command"",""メールアドレスが存在しません" >> "error_no.txt"}'
    elif grep -o "DATA" TEMP2.txt > /dev/null
        then
            awk 'BEGIN {print "in reply to end of DATA command"",""メールを受信できない状態です" >> "error_no.txt"}'
    else
            awk 'BEGIN {print "不明"",""メールが届きませんでした" >> "error_no.txt"}'
    fi
done

 

これで、とりあえず全てのファイルからメールアドレスを抜き出した。sort | uniq をかけなかったのは抽出順を変えないため。当然、離れた場所に重複があればそのまま。これは仕様。隣接する重複だけを除去している。つまり、エラーログファイルにいくつも同じメールアドレスがあるので、それだけを対象にしている。

 

で、メールアドレスを格納した TEMP4.txt とエラー理由を収めた csv ファイル error_no.txt が出来上がり。エラー理由は、

1.メールアドレスが存在しない。

2.受信側でメールを受信できない状態。

3.その他の理由は全て不明に。

と大雑把に分けている。

 

ここからが問題で、 TEMP4.txt に収めたメールアドレスをキーに、顧客データの csv ファイルを1行抜き出す。本当は、同一メールアドレスで複数の顧客(チェーン店などは同じメールアドレスで複数店舗存在するから)がヒットするが、それは別処理(Excel + VBA)としてとりあえず1行抜き出す。

 

こんな感じ。

 

while read LINE
do
    if    OUTPUT=`echo $LINE | xargs -I{} grep -w -m1 {} address_utf8.csv`
        then
        awk -v "sh=$OUTPUT" 'BEGIN {print sh >> "TEMP5.txt"}'
    else
        echo $LINE
    fi
    unset OUTPUT
    unset LINE
done < ./TEMP4.txt

Windows の Excel で読めるように

 

nkf -s error_no.txt > error_no.csv
nkf -s TEMP5.txt > output.csv

 

として作表用の原版を作成。重複行は

 

sort TEMP5.txt | uniq -d > TEMP6.txt
nkf -s TEMP6.txt > 重複行.txt

 

としてある。ここから先は、Excel + VBA のお仕事。とりあえずのテストだが何とか目的は果たせた。

 

悩んだのは、

 

    if    OUTPUT=`echo $LINE | xargs -I{} grep -w -m1 {} address_utf8.csv`

 

そもそも、メールアドレスはメタキャラクタ `@' が必須。シェル変数展開時、grep に対してエスケープしても、次は bash で引っかかる。そこで1回 echo で出力してから引数として新たに与えた。これで無事動作。unset はおまじない。

 

上記、たかが1行のスクリプトだが、悩んだ。xargs が無ければどうなったことやら… シェル作成の達者なら何でもないことでも滅多にしない私は散々だった。