初級コマンド編 レコード選択1(xtsel)

レコードの選択は非常に重要な処理で、MUSASHIでは多様な選択条件を記述することができる。
レコード選択の中心となるコマンドが本章で解説するxtselコマンドである。

ここでは、先に作成したスクリプトxtcut.shを再利用することにする。FDで、前章でおこなった手順で、xtcut.shをxtsel.shの名前でコピーしておこう。
新しくコピーされたファイル"xtsel.sh"を編集する。
まずは、xtcutが出力するデータに対して、日付が1996年01月20日のデータだけを抜き出すことから始めよう。
xtselコマンドは -cパラメータで選択条件式を記述する。但し条件式の中で項目名の前には必ず"$"を付ける必要がある。
目的の条件式は次のようになる。'$日付==19960120'。ここで、"=="は数値比較演算子である。左右の値が同じであれば「真」を返し、同じでなければ「偽」を返す。xtselコマンドは条件式が真を返す行のみを選択する。その他の多様な比較演算子については後述する。
また注意点として、条件式には、様々な記号が含まれるので、通常は、条件式全体をシングルクオーテーションで囲む必要がある。そうしなければ、例えば$日付は、bashが環境変数として解釈してしまうため、期待どおりの動作をしない。
さて、このxtselコマンドを追加したスクリプトは以下のようになる(そして最後に、出力ファイル名(xtcount.xt)、およびコメントの変更も忘れずに)。

#/bin/bash
#===============================================================
# MUSASHI bash script
#===============================================================

#---- タイトル
title="チュートリアル"

#---- コメント
comment="xtsel"

#---- 各種変数(適宜修正すること)
inPath="/mnt/h00/prm/tutorial"

#---------------------------------------------------------------
# コマンド
#---------------------------------------------------------------
xtcut -f 日付,数量,金額 -i $inPath/dat.xt.gz |
xtsel -c '$日付==19960120' |
xtheader -l "$title" -c "$comment" -o xtsel.xt
#===============================================================

ここで指定した三行の意味は次の通りである。
xtcutで「日付」、「数量」、「金額」の項目を選択し、その結果をパイプラインで次のxtselコマンドに送る。xtselコマンドでは、条件式「日付項目が19960120等しい」にマッチする行を選択する。そして、その結果データは再びパイプラインによって次のxtheaderコマンドに送られる。xtheaderコマンドは、タイトルとコメントを変更し、その結果を"xtsel.xt"というファイルに書き込む。

スクリプトの編集が終れば保存して、実行する。結果データを確認すると1996年01月20日のデータが選択されていることを確認できるであろう。

さて、ここでxtselコマンドが提供する基本的な比較演算子について見ておこう。下図はxtcalで利用可能な基本的な比較演算子一覧である。

演算子 意味
== 左右の数値が等しい
< 左が右の数値より小さい
<= 左が右の数値以小
> 左が右の数値より大きい
>= 左が右の数値以上
<> 左右の数値が等しくない
-eq 左右の文字列が等しい
-gt 左が右の文字列より小さい
-ge 左が右の文字列以上
-lt 左が右の文字列より大きい
-le 左が右の文字列以下
-ne 左右の文字列が等しくない
|| 左右の条件式の論理和
&& 左右の条件式の論理積
=~ 正規表現によるパターンマッチ

これらの演算子を使い先のスクリプトにおけるxtselの条件式を変更してどのように動作するかを確認していこう。
まず最初に文字列比較についてである。xmlTableでは、項目の型が存在しない。あえて言えば全て文字列型である。それゆえに、項目の値をどのように扱うかは、条件式の書き方次第ということになる。例えば先に示した'$日付==19960120'という条件式での演算子"=="は左右の値を数値と見なして比較をする。これを文字列として比較したければ'$日付 -eq "19960120"'ということになる。ここで文字列定数はダブルクオーテーションで囲わなければならない。それでは先のスクリプトを文字列比較の式に変更して実行しよう。スクリプトは以下のようになる。実行結果は、前の結果と全く同じになるはずである。

#/bin/bash
#===============================================================
# MUSASHI bash script
#===============================================================

#---- タイトル
title="チュートリアル"

#---- コメント
comment="xtsel"

#---- 各種変数(適宜修正すること)
inPath="/mnt/h00/prm/tutorial"

#---------------------------------------------------------------
# コマンド
#---------------------------------------------------------------
xtcut -f 日付,数量,金額 -i $inPath/dat.xt.gz |
xtsel -c '$日付 -eq "19960120"' |
xtheader -l "$title" -c "$comment" -o xtsel.xt
#===============================================================

次に、条件式を"&&"で連結する方法について見てみよう。例えば、「数量が5より大きく、かつ、金額が1000以上」の行を抜き出すためには、条件式として'$数量>5 && $金額>=1000'と指定する。スクリプトは以下のようになる。

#/bin/bash
#===============================================================
# MUSASHI bash script
#===============================================================

#---- タイトル
title="チュートリアル"

#---- コメント
comment="xtsel"

#---- 各種変数(適宜修正すること)
inPath="/mnt/h00/prm/tutorial"

#---------------------------------------------------------------
# コマンド
#---------------------------------------------------------------
xtcut -f 日付,数量,金額 -i $inPath/dat.xt.gz |
xtsel -c '$数量>5 && $金額>=1000' |
xtheader -l "$title" -c "$comment" -o xtsel.xt
#===============================================================

結果を確認すれば、条件どおりの行のみが選択されているのが確認できるであろう。
ここで重要なことは、演算子を複数用いる場合は、その優先順位を考慮に入れなければならない、ということである。例えば、先の例では、3つの比較演算子(>、&&、>=)を用いている。
>と>=演算子は&&演算子よりも優先される。また>と>=は優先順位に差がないので、出現順となる。例えば、条件式「$数量>5 && $金額>=1000」では、まず「$数量>5」が評価され、次に「$金額>=1000」が評価される。そして最後に「&&」の演算子が評価される。これらの優先順位を変更したければ括弧を用いればよい。
例えば、次のような条件式を考えて見よう。
「日付が19960115より大きいデータの中で、数量が5より大きい、もしくは、金額が1000以上」
この条件について、条件式'$日付>19960115 && $数量>5 || $金額>=1000'は、「日付が19960115より大きく、かつ数量が5より大きいデータ、もしくは金額が1000以上のデータ」となってしまう。
そこで条件式に括弧を入れ、'$日付>19960115 && ($数量>5 || $金額>=1000)'とすればよい。スクリプトを変更して、それぞれの場合にどのようなデータが選択されるかを確認しよう。

さて最後に、算術演算子を含んだ比較式について紹介しておこう。xtselでは、比較演算子だけでなく、様々な演算子や関数を用いることができる。詳細は「項目間演算(xtcal)」を参照してもらいたい。
ここでは簡単に、割り算を用いた条件式について見てみよう。

これまでに用いてきたデータで金額とは商品単価×数量によって計算された値である。そこで、商品単価が100円以下の商品を選択する条件式を考えると次のようになる。
'($金額/$数量) <=100'。ここで"/"は割り算の演算子である。この式の意味は「金額を数量で割った値が100以下」である。
この式を反映させたスクリプトは下図のようになる。実行し結果を確認すれば、単価が100円以下の行が選択されているのがわかるであろう。

#/bin/bash
#===============================================================
# MUSASHI bash script
#===============================================================

#---- タイトル
title="チュートリアル"

#---- コメント
comment="xtsel"

#---- 各種変数(適宜修正すること)
inPath="/mnt/h00/prm/tutorial"

#---------------------------------------------------------------
# コマンド
#---------------------------------------------------------------
xtcut -f 日付,数量,金額 -i $inPath/dat.xt.gz |
xtsel -c '($金額/$数量)<=100' |
xtheader -l "$title" -c "$comment" -o xtsel.xt
#===============================================================

OnePoint 文字列比較と数値比較の違い
本章で見た日付項目に関する数値比較と文字列比較では、結果が全く同じになったが、これらの比較は実は全く異なるものである。これは値の順序を考えれば明白である。例えば、"20"と"100"という値を数値として見た場合、当然100の方が大きい。しかし、文字列として見た場合は"20"の方が大きいと判断される。文字列の比較においては、文字列を先頭文字から順番に、その文字コードの大きさで比較していく。まず"20"の"2"と"100"の"1"を比較する。この時点で、文字コードでは"1"より"2"の方が大きい。よって"20"のほうが大きいと判断される。日付比較で同じになったのは、日付項目が固定長(8文字)であったからである。

練習課題

この章で利用したスクリプトのxtselの条件式を変更して次のようなデータを作成しよう(3つ目以降はxtcalの後にxtaggコマンドが必要)。