OKWAVEのAI「あい」が美容・健康の悩みに最適な回答をご提案!
-PR-
解決
済み

またまたこづかい帳です~

  • すぐに回答を!
  • 質問No.192115
  • 閲覧数57
  • ありがとう数3
  • 気になる数0
  • 回答数3
  • コメント数0

お礼率 80% (4/5)

こんばんは。こづかい帳作っててまた分からなくなっちゃいました。
環境は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コマンドした時点で
消えちゃってるや。。。ダメじゃ~ん(笑)分かる方教えて下さいな~
通報する
  • 回答数3
  • 気になる
    質問をブックマークします。
    マイページでまとめて確認できます。

質問者が選んだベストアンサー

  • 回答No.1
レベル13

ベストアンサー率 34% (574/1662)

今回は、何がしたいのかがよくわかりません。
見たところ,集計もせずにデータを増やしているだけですし。

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


まずは、何のために、どういうものをつくりたいのかはっきりさせましょう。
補足コメント
heikekaori

お礼率 80% (4/5)

お返事ありがとう。
うーん、全くその通りですね(^^;
ただ単にデータを増やしているだけだ~(>_<)
「何のためにどういうものをつくりたいのか」だけど、
「こづかいの集計機能の体得のために」
「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:09
お礼コメント
heikekaori

お礼率 80% (4/5)

あれ。なんかterra5さんが補足した形になっちゃいました。
ごめんなさい。
投稿日時 - 2002-01-06 17:32:34
-PR-
-PR-

その他の回答 (全2件)

  • 回答No.2
レベル13

ベストアンサー率 34% (574/1662)

まずは目的から. >「logを集計してグラフで分かり易くしたい」 どういうグラフを作りたいのでしょうか? 今回のは時刻ごとに使った金額を集計して、それをグラフ化したいということでしょうか? >それは一日一回logを集計して、終わったら元データを消すことにしたからです。 これももっと明確にしないとプログラムはできません。 どういった集計をして、どういう形のデータをつくるのが不明です。 ...続きを読む
まずは目的から.

>「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"になりますが、問題ありませんか?
お礼コメント
heikekaori

お礼率 80% (4/5)

>>「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:30
  • 回答No.3
レベル13

ベストアンサー率 34% (574/1662)

らちがあかないので、そろそろ逃げます(^^;; やろうとしていることをうまく文章にまとまめられないと、こういう場では私には対応は無理です. また、文章でないにしても、具体的にこういうデータでこういうスクリプトで処理するとこうなったが、 どこを直せばよいかとか. 今のだと、入力データも出力結果も実際に使ったスクリプトも判らなくて,判断できません. 現状だと、おそらく直接会っていろいろ話 ...続きを読む
らちがあかないので、そろそろ逃げます(^^;;

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

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

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

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

お礼率 80% (4/5)

うん。ありがとね。色々教えてくれてほんと嬉しかったよ☆
残念だけど(:_;)またいつか整理して現れます~♪
ほんとにさんきゅ~~~~~
PS.同じ人に「良回答」と「次点」どっちも付けられないんだね。
  terra5さんに気持ちの上では30POINT!!!
投稿日時 - 2002-01-10 22:05:19
このQ&Aで解決しましたか?
関連するQ&A
-PR-
-PR-
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する
-PR-
-PR-
-PR-

特集


いま みんなが気になるQ&A

関連するQ&A

-PR-

ピックアップ

-PR-
ページ先頭へ