1012345678910111213141516171819202122232425262728293012

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
【 --/--/-- (--) 】 スポンサー広告 | TB(-) | CM(-)

Bashで正規表現など使いデータの精査(数値データ)

先日のbashの中で直接正規表現を使いボロボロなデータファイルの精査をする件の続き。

[[ string =~ regex ]]と書けば、文字列stringが正規表現パターンregexにマッチするかどうかをbashの中で直接評価できると書いた。

じゃぁ、たとえばどんな正規表現を使えば、データの検証ができるか...

まずは数値をあらわす文字列について。


固定長整数、カンマ区切り・小数点・符号など一切なし




[[ ${FIELD} =~ ^[0-9]{8}$ ]] || BAD_DATA_FLAG=1


正規表現を既に使ってる人には耳蛸だけど、基礎をあらためて書くと...
・数字0~9のうち任意の1文字を表すパターンは、[0-9]というかたちであらわす。
・大カッコでくくると、大カッコの中の任意の1文字という意味。
 さらに、0-9と書くことで、「0から9までの」という意味。
・中括弧「{}」の中に数が一つだけ書いてあると、その文字数という意味。
・大カッコの前にあるキャレット(^)は、冒頭を意味し、大カッコの後ろにあるドルマーク($)は末尾を意味する。
 なので、^と$の間にパターンを書くと、そのパターン以外の文字は存在しない、というかたちになる。


n桁以内の整数、カンマ区切り・小数点・符号など一切なし




[[ ${FIELD} =~ ^[0-9]{,8}$ ]] || BAD_DATA_FLAG=1


先ほどの正規表現との違いは、中括弧が{,8}というようにカンマを使っている点。これは、カンマの右に書いてある数までの文字数、という意味。つまり、
{8} … 8文字
{0,8} … 8文字以内 (なぜか、{,8}と書くと正しく文字数を判定してくれない。)
{8,} … 8文字以上
{4,8} … 4文字以上8文字以内
というような使い方ができる。


整数もしくは小数、カンマ区切り・小数点・符号などあり、スペースも含む




[[ ${FIELD} =~ ^[\+\-]*[ ]*[0-9]{1,3}(,[0-9]{3})*(\.[0-9]{0,15}){0,1}$ ]] || DATA_ERROR_FLG=1


Excelなどからテキストファイルをエクスポートすると、凝った書式が残ったままの場合があり得る。
また、数値としても、現実世界には負の数もあれば小数もある。
そのようなデータを扱う正規表現パターン。


指数表記の数値



Float型の数値の場合、"-3.14159265758979E002"(-314.14159265758979という意味)のように、指数表記である事が多い。
そのような書き方をされた数値の場合


[[ ${FIELD} =~ ^[\+\-]*[1-9](\.[0-9]{0,15}){0,1}[eE][\+\-]{0,1}[0-9]{1,3}$ ]] || DATA_ERROR_FLG=1



数値の小数点より上の桁数、下の桁数を調べる



数値型としか定義書にかかれておらず、小数点の上、下それぞれ何ケタ必要か調べないといけない場合がある。
残念ながら説明レベルでとどまっていて構築可能なレベルに達していない仕様書も世の中には数多く存在する。

そういう場合に、実データをなめてDECIMAL型の小数点より上・下の桁数が何ケタ必要かを調べる方法。
(もちろん、仕様としては必要だけど「たまたま」そういうデータがなかったという理由で、必要分より少ない桁数をレポートする場合もあり得るけど...それは仕方のない話。ちゃんと文書に起こしておけ、ムカー。)

これには、これまで使ってきた正規表現マッチとは異なる方法を用いる。

 
tmp_field=${FIELD//[,\.\-\+ ]/}
tmp_above=${FIELD%.*}
tmp_below=${FIELD#*.}
digits_above=${#tmp_above}
digits_below=${#tmp_below}


ちょっと長ったらしくて、一行で書き表せないのが残念なところ。
これら新たに出てきた表記法は、文字列に対してでなくパラメータ(変数)に対してしか使えないので、ひとつ処理するたびに代入し直さないと、凝った事ができないのだ。
(bashのメンテナーのみなさん、何とかしてもらえませんか?)

新たに出てきた表記法をざっくり説明すると、

${param//pattern/subst} … 変数paramの内容に対し、パターンpatternにマッチする部分をsubstの値に変換して表示する。
つまり、sedでよくやる's/pattern/subst/g' と同じような使い方。
ただし、凝った正規表現は書けない。せいぜいファイル名展開に使うパターンの程度。
${param/pattern/subst}とも書け、その違いは、'/'が一つだとパターンに1回マッチしたところまでで止め、2つ('//')だと変数のあらわす文字列全てに対して行う。
${param%pattern} … 変数paramの内容の末尾部分に対し、パターンpatternがマッチするかチェックし、マッチした部分を削除した内容を表示する。



・参考リンク
Manpage of BASH--JM Project
スポンサーサイト
【 2014/02/26 (Wed) 】 未分類 | TB(0) | CM(0)
コメントの投稿












管理者にだけ表示を許可する
トラックバック
この記事のトラックバックURL

プロフィール

Ed U Song

Author:Ed U Song
社内ノマドなエンジニア。
仕事で触れる機会のないものを自宅環境作って実験。

スポンサーリンク
最新コメント
最新トラックバック
検索フォーム


                                         
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。