プロが教える店舗&オフィスのセキュリティ対策術

こんばんは。こづかい帳作っててまた分からなくなっちゃいました。
環境はgawkとbashを用いてlogの集計を行っています。

1/1 gohan 1000
1/1 kaimono 5000
1/1 kaimono 2000
1/2 karaoke 3500
1/2 gohan 1200
1/2 gohan 1500

前回このようなlogを元に集計しました。おかげ様で

1/1 gohan 1000
1/1 kaimono 7000
1/2 karaoke 3500
1/2 gohan 2700

このように集計することが出来ました。ありがとうございます。
でも、ここで時間も入れることにしました。その代わり日付はいりません。
それは一日一回logを集計して、終わったら元データを消すことにしたからです。
07:00 gohan 500
11:00 kaimono 2000
12:00 gohan 1000
15:00 oyatu 300
19:00 gohan 2000
というのがありまして、これを
00:00 0 0
01:00 0 0
02:00 0 0
03:00 0 0
04:00 0 0
05:00 0 0
06:00 0 0
07:00 gohan 500
08:00 0 0
09:00 0 0
10:00 0 0
11:00 kaimono 2000
12:00 gohan 1000
13:00 0 0
14:00 0 0
15:00 oyatu 300
16:00 0 0
17:00 0 0
18:00 0 0
19:00 gohan 2000
20:00 0 0
21:00 0 0
22:00 0 0
23:00 0 0
という風にすることは出来るんですか?これをしようとした時に
初めから元のデータに
00:00 0 0
01:00 0 0
02:00 0 0
続く
22:00 0 0
23:00 0 0
を追加してみて、時間のところが重複したら消すとかやるのかな~と
思ったんですが、そのことを先生に話したら、勝手にデータに追加するなんて
ナンセンスだ!って言われちゃいました。それはそうですよね。。。^^
でもuniqコマンドってありますよね。このやり方でも出来ますか?
uniqコマンドして$2>0なら消す。。。あれ?uniqコマンドした時点で
消えちゃってるや。。。ダメじゃ~ん(笑)分かる方教えて下さいな~

A 回答 (3件)

今回は、何がしたいのかがよくわかりません。


見たところ,集計もせずにデータを増やしているだけですし。

単に、1時間単位で出力して、データが無ければ 0 を出すというのは作れますが,意味がなさそうなのでやる気はありません(^^;;;
結局、月ごとに集計するのなら、無駄なデータを追加するだけですし。


まずは、何のために、どういうものをつくりたいのかはっきりさせましょう。

この回答への補足

お返事ありがとう。
うーん、全くその通りですね(^^;
ただ単にデータを増やしているだけだ~(>_<)
「何のためにどういうものをつくりたいのか」だけど、
「こづかいの集計機能の体得のために」
「logを集計してグラフで分かり易くしたい」
です。グラフは集計後のlogをftpを使って自分のパソコンに取り込んで、
Excelでグラフ化するつもりです。でも、
ほんとはね、集計する時にちゃんと1時間づつ区切って
24個のlogを作るつもりだったんだよ。
でも、分からなかったの。あ、違う。えーとー、
{
for(i=1;i<=24;i++){
if((100*(i-1) <= $1) && ($1 < 100*i)){
count[i]++
}
}
}

END{
for(i=1;i<=24;i++){
if(count[i] != 0){
print i,count[i]
} else {
print i,0
}
}
}
ってやると、データがない時に0出るよね?でも、集計する時に
{
if(length($2) > 0){
kazu[$2] ++;
}
}

END{
for(i in kazu)
print $1,i,kazu[i]
}
ってのを使う場合、for文ってのは同じだけど、これってawk独特の
連想配列ってやつとかで、これと先に書いたfor文を組み合わせることが
できないんです。それか、前に教えてもらった
{
sum[$2,$3] += $4
}

END {
for(item in sum){
split(item, t, SUBSEP );
printf("%s %s %s %d\n",$1,t[1],t[2],sum[item]);
}
}
これだって、連想配列ですよね?結局、集計が終わってから
「あ、0のデータがない…。」って気付いて、
後から0のデータをくっつけるってことになっちゃったんです。
どうしたらいいですか~?あ、今考えてる方針、
自分が思ってるの言います。時間のフィールドで
23:00だったら、FS=":"ってやってjikan=$1*3600ってやれば
秒数が出ますよね。ここでまた新たに
for(i=1;i<=24;i++){
if((3600*(i-1) <= jikan) && (jikan < 3600*i)){
print strftime("%H:%M",jikan),$2,$3
} else {
print strftime("%H:%M",jikan),0,0
}
}
ってやればいいんですか?

補足日時:2002/01/06 02:31
    • good
    • 0
この回答へのお礼

あれ。なんかterra5さんが補足した形になっちゃいました。
ごめんなさい。

お礼日時:2002/01/06 17:32

まずは目的から.



>「logを集計してグラフで分かり易くしたい」
どういうグラフを作りたいのでしょうか?
今回のは時刻ごとに使った金額を集計して、それをグラフ化したいということでしょうか?

>それは一日一回logを集計して、終わったら元データを消すことにしたからです。
これももっと明確にしないとプログラムはできません。
どういった集計をして、どういう形のデータをつくるのが不明です。


文章中で個々に気になる点を。

> if((100*(i-1) <= $1)

$1には例えば"01:00"が入っていますよね?
これと数値を比較するのは好ましくないと思います.
通常は,ここから"01"の部分だけを数値化して比較するのが正しいでしょう.

>if(length($2) > 0){
$2は例えば,"0"とか"gohan"がはいりますよね?
何のための処理かわかりません。

>awk独特の連想配列ってやつとかで、これと先に書いたfor文を組み合わせることが
>できないんです。

連想記憶はperlにもあります。
また、forの組み合わせが出来ないと言う意味もわかりません。
どういうことがやりたいのか判らないので,答えられません.

>23:00だったら、FS=":"ってやってjikan=$1*3600ってやれば
>秒数が出ますよね。
行の内容が"23:00 0 0"の場合、FS=":"とすると
$1=="23" $2=="00 0 0"になりますが、問題ありませんか?
    • good
    • 0
この回答へのお礼

>>「logを集計してグラフで分かり易くしたい」
>どういうグラフを作りたいのでしょうか?
>今回のは時刻ごとに使った金額を集計して、それをグラフ化したいということ
>でしょうか?
そうですね。何かうまく伝わらないようでたびたびすみません。
時刻ごとに使った用途と金額の表が元になって、
棒グラフでOKです。

>>それは一日一回logを集計して、終わったら元データを消すことに
>>したからです。
>これももっと明確にしないとプログラムはできません。
>どういった集計をして、どういう形のデータをつくるのが不明です。
えーと、これは。一日一回cronにお願いして、0:00ちょっと前
(23:58ぐらいの予定なんですが)に元データを削除し、
また最初からデータを取り始める。だから、日にちの部分は
システム時刻から持ってくればいいかなって。

>> if((100*(i-1) <= $1)
>$1には例えば"01:00"が入っていますよね?
>これと数値を比較するのは好ましくないと思います.
>通常は,ここから"01"の部分だけを数値化して比較するのが正しいでしょう.
あ、これはすみません。この連想配列の部分だけは
適当にサンプルから持ってきたものです。数値と時刻を
比較するつもりはありませんのです。

>>if(length($2) > 0){
>$2は例えば,"0"とか"gohan"がはいりますよね?
>何のための処理かわかりません。
これは、「$2に文字列があったら」って意味です。
「gohan」これは間違いなく文字列ですよね。その時は
カウントする。また「karaoke」についても
別の連想記憶で(?)カウントする。
END文でカウントしたのをprintするってつもりなの。

>>awk独特の連想配列ってやつとかで、これと先に書いたfor文を
>>組み合わせることができないんです。
>連想記憶はperlにもあります。
>また、forの組み合わせが出来ないと言う意味もわかりません。
>どういうことがやりたいのか判らないので,答えられません.
連想配列(連想記憶?)って言うのは、for文ですよね。
あ、for文じゃなくてもいいのかな。count[i]のようにして
count[1]、count[2]、count[3]…。にそれぞれ値を入れるってことですよね?
これとfor(i=1;i<=24;i++)というfor文は区別されるんじゃないんですか?
構文の使い方が違いますよね?私は連想配列って言うのを、
多種の項目(gohanとかkaraokeとか)それぞれの個数を、カウントすることが
出来る構文として知り始めたんです。だからなのか、for(i in count)形式の
ものとfor(i=1;i<=24;i++)の形式のものを区別して考えてしまいます。
例えば10行のlogがあったとしますよね。ここでfor(i in count)形式を
使いカウントをしたとしますよね(カウント以外にもあるんだろうけど)。
結果、出力されるlogって言うのは10行以下ですよね(集計されて)。
これは集計が行われたと言えると思います。じゃ、for(i=1;i<=24;i++)形式を
使用して、if(((i-1) <= $1) && ($1 < i))にあてはめるとすると、
iが1の場合について10回処理。2の場合について10回処理。
結果、240行以下のlogが出力される。if文のelse部にprintを使ったり
しなければ、for(i=1;i<=24;i++)形式同様10行以下の出力になるでしょうけど、
私は今、0:00の行にgohanがなかったら、0 0とくっつけたいわけですから、
else文にその場合を書くことになりますよね。すると、iが1の時、2の時、
それぞれについて10行出力されてしまうわけで、結局やっぱり
240以下のlogが出力されてしまいます。そうすると
00:00 0 0
00:30 karaoke 1500
00:30 0 0
01:00 0 0
ということになっちゃいまして、
その場合は00:30 0 0の部分は不要なんですよ。
だから、これを消すのかなって思ったんです。
例えば、for(i in count)形式とfor(i=1;i<=24;i++)形式が
同じブロック内とか、メインループとENDブロックとか、
そのように使われている例とかありますか?
それって可能なのですか?うーん、うまく言えません。

07:00 gohan 500
11:00 kaimono 2000
12:00 gohan 1000
15:00 oyatu 300
19:00 gohan 2000
このように出力するのは、
{
sum[$2,$3] += $4
}

END {
for(item in sum){
split(item, t, SUBSEP );
printf("%s %s %s %d\n",$1,t[1],t[2],sum[item]);
}
}
これを使いました。この時点で、
{
for(i=1;i<=24;i++){
if((3600*(i-1) <= jikan) && (jikan < 3600*i)){
print strftime("%H:%M",jikan),$2,$3
} else {
print strftime("%H:%M",jikan),0,0
}
}
これのように$2が一致しなかったら0 0を返して、
00:00 0 0
01:00 0 0
02:00 0 0
03:00 0 0
04:00 0 0
05:00 0 0
06:00 0 0
07:00 gohan 500
08:00 0 0
09:00 0 0
10:00 0 0
11:00 kaimono 2000
12:00 gohan 1000
13:00 0 0
14:00 0 0
15:00 oyatu 300
16:00 0 0
17:00 0 0
18:00 0 0
19:00 gohan 2000
20:00 0 0
21:00 0 0
22:00 0 0
23:00 0 0
というのを出力させることは可能ですか?

>>23:00だったら、FS=":"ってやってjikan=$1*3600ってやれば
>>秒数が出ますよね。
>行の内容が"23:00 0 0"の場合、FS=":"とすると
>$1=="23" $2=="00 0 0"になりますが、問題ありませんか?
問題ないと思うんですが…。$1が23なんですから、
jikan=23*3600ってなって、23:00を見事に秒数に変換出来たって
言えるんじゃありませんか?それをファイルに入れると、
$1は82800になり、ここで改めて
{
for(i=1;i<=24;i++){
if((3600*(i-1) <= $1) && ($1 < 3600*i)){
print strftime("%H:%M",$1),$2,$3
} else {
print strftime("%H:%M",$1),0,0
}
}
に当てればいいのかなって。

分からないところだらけだろうとは思うんですが、
私も一応必死になって説明してるつもりなんです。
またご指摘頂ければ、もっと頑張って状況説明します。
だからなんとかお願いします。長くてほんとごめんなさい。

お礼日時:2002/01/07 23:40

らちがあかないので、そろそろ逃げます(^^;;



やろうとしていることをうまく文章にまとまめられないと、こういう場では私には対応は無理です.

また、文章でないにしても、具体的にこういうデータでこういうスクリプトで処理するとこうなったが、
どこを直せばよいかとか.
今のだと、入力データも出力結果も実際に使ったスクリプトも判らなくて,判断できません.

現状だと、おそらく直接会っていろいろ話ながら数時間かかると思います。

前回の内容からすると,やることが飛躍的に増えすぎていて収集つかなくなっているようにも感じますので、
もう少しやりたいことを絞り込んでやり直したほうがいいと思います.
    • good
    • 0
この回答へのお礼

うん。ありがとね。色々教えてくれてほんと嬉しかったよ☆
残念だけど(:_;)またいつか整理して現れます~♪
ほんとにさんきゅ~~~~~
PS.同じ人に「良回答」と「次点」どっちも付けられないんだね。
  terra5さんに気持ちの上では30POINT!!!

お礼日時:2002/01/10 22:05

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!