68user's page 掲示板

Prev< No. 4280〜4299> Next  [最新発言に戻る] [過去ログ一覧]
No. 4280 # くま 2005/09/09 (金) 01:17:16
Solaris8i、shシェルで以下のような処理をしようとしています。
番号が同じもの同士の値を足し算してその和を求めています。

ファイルフォーマット
番号,値
001,10
001,20
001,30
002,5
003,15
003,20
004,100

結果
001,60
002,5
003,35
004,100

としたいのですが、どうすればよいですか。

No. 4281 # zsh 2005/09/09 (金) 13:45:10
>>4280 くま
Solarisi・・・って部分は置いといて。

shというかnawkですが、以下のようにやればできます。
(awkでは動きません。)
------------------------
$ nawk -F, '
        /^[0-9]+,[0-9]+$/ {
                var[$1] = $2;
        } END {
                for (i=0; i<=999; ++i) {
                        j = sprintf("%03d",i);
                        if (j in var) print j "," var[j];
                }
        }' data.txt
------------------------

No. 4282 # zsh 2005/09/09 (金) 17:58:45
>>4281 zsh
>Solarisi・・・って部分は置いといて。
間違えた・・・Solaris8iだ・・・

No. 4283 # nagadomi [E-mail] 2005/09/09 (金) 22:41:30
はじめまして。ネットワークプログラミングのページを参考にさせてもらっています。
で、以下の部分、
>>DNS クライアントを作ってみよう (3)
>リソースデータは「&Sorry, no version string is available」と表示されるが、
>dig や nslookup は「Sorry, no version string is available」となります (& がない)。
>先頭の & を削るような規則があるようだが、それが何なのかはわからなかった。

これ、'&'=38で、リソースのlengthみたいです。
きちんとした資料では、まだ見つけられていないのですが、
djbdnsのソースコード(dns_txt.c)上では、ドメイン名と同じように、
[length][data][length][data]と見ているようです。
リソースをいくつかのブロック(例えばライン毎など)に分けているのかなーと。

んん。標準な資料を探し中です。

No. 4284 # nagadomi [E-mail] 2005/09/09 (金) 22:44:42
>>4280 くま
Solaris8iは手元にないので試していないですが、shで。

---------------------------
#!/bin/sh

# デリミタを[,]に
IFS=,

# キーのリスト
list=""

# 計算
while read key value; do
                eval "if test -z \$array$key;then array$key=0; fi"
                eval \array$key=`eval "expr \\$array\$key + \$value"`
                list=$list,$key
done < data.txt

# 重複したキーを削除する
clone=`echo "$list" | sed 's/^,//'`
for key in $clone; do
                list=`echo "$list" | sed "s/$key//g" | sed 's/,[,]*/,/g'`
                list=$list,$key
done

# 表示
list=`echo "$list" | sed 's/^,//'`
list=`echo "$list" | sed 's/,$//'`

for key in $list; do
                echo -n $key,
                eval echo \$array$key
done
---------------------------
$ sh test.sh
001,60
002,5
003,35
004,100
---------------------------

効率悪そうだ..。

No. 4285 # シャチ 2005/09/10 (土) 10:00:34
>>4280 くま
以下ので出来ると思います。

----------------------------------
#!/bin/sh

nawk -F"," '
        BEGIN {
        }
function syukei() {
        total=0+0;
        no=$1;

        while (NF>0) {
                if (no == $1) {
                        total = total + $2;
                } else {
                        printf("%03d:%d\n",no,total);
                        no=$1;
                        total=$2;
                }
                getline;
        }
        printf("%03d:%d\n",no,total);
}
{
        if (NF == 0) next ;
        syukei() ;
}' file.txt

exit 0

No. 4286 # nagadomi 2005/09/10 (土) 22:58:12
続々と投稿されているので投稿してみます。

>>4280 くま
awkなら、
$ nawk -F, '{v[$1]+=$2;}END{for(k in v) print k","v[k]}' data.txt | sort
とできると思います。
/+ data.txt -> データファイル +/

No. 4287 # シャチ 2005/09/11 (日) 15:03:55
>>4286 nagadomi

nagadomiさんのコード凄いですね。
1行で実現してしまうなんて。
自分も、1行で実現できないかと試みてはみたのですが、良い案が浮かび
ませんでした。

向学として教えていただきたいのですですが、
番号の比較、判断していませんが、何故、上手く出来ているのですか。

>'{v[$1]+=$2;}END{for(k in v) print k","v[k]}'
宜しくお願いします。

No. 4288 # zsh 2005/09/11 (日) 20:20:12
>>4286 nagadomi
うわー、awkってforでその表記できるんだっけー。
すっかり忘れてました。
最近awk触っていなかったとは言え、恥ずかしい・・・

>>4287 シャチ
>for(k in v)
は、配列vの値を一つ一つ変数kに代入してループするという意味です。

No. 4289 # zsh 2005/09/11 (日) 23:44:55
>>4288 zsh
×配列vの値を一つ一つ変数kに代入してループする
○配列vの添字を一つ一つ変数kに代入してループする

No. 4290 # nagadomi 2005/09/12 (月) 03:38:59
>>4287 シャチ
zshのおっしゃるとおりです。
Perlでいうforeach的な使い方です。

>>4288 zsh
awkは、1年ほど前に1日(プログラム一個..)使ったことがあるだけだったので、
実はリファレンスをちょっと見ました。
そこでforeachあるじゃんと..。知らない分、確認するのでうまくいった感じですかね..。

zshさんのコードは、ソートを考えて、あのような書き方をしているのかと思っていました。
私は普段、こういうのにはPerlを使っています。

No. 4291 # シャチ 2005/09/12 (月) 11:55:17
>>4288 zsh

番号の比較、判断していませんが、前後が同じかどうかの判断は
どこでしているのですか。
>{v[$1]+=$2;}
で判断しているのですか。
お願いします。

>>4290 nagadomi
Perlを使うのが便利なのですか。
Perlは、人が作ったのをメンテナンスするため1日調べたのみです。

No. 4292 # シャチ 2005/09/12 (月) 13:52:41
>>4288 zsh

配列vの添え字が、番号なんですね。
だから、番号の配列要素に割り当てられた値が使用できるから
番号の比較、チェックが不要なんですね。

添え字には、数値しか使用できなと思っていました。
文字列も使えるんですね。

No. 4293 # 68user 2005/09/13 (火) 00:28:29
>>4283 nagadomi
なるほど、length ですか。RFC をあさってみましたが、まだ見つけられません。
発見したらぜひ教えてください。

関係あるかな? と思いつつ、まだちゃんと読んでいない資料:
    http://www.cs.utah.edu/~danderse/adns/arch.html
    http://www.zeroconf.org/Rendezvous/txtrecords.html

No. 4294 # hagu 2005/09/16 (金) 02:32:13
Solaris8で、Bシェル(sh)で以下のことを行いたいのですが、
良い方法を教えてください。

2つのファイルの中身を比較し、その結果を表示したいのです。
--- file1.txt -----
hanako.sato
jiro.yamamoto
taro.yamada
taro-1.yamada
tsuyoshi.saito


--- file1.txt -----
jiro.yamamoto
taro-1.yamada
taro-2.yamada
gou.yamashita

結果
file1 Only, hanako.sato
match,jiro.yamamoto
file1 Only,taro.yamada
match,taro-1.yamada
file1 Only,tsuyoshi.saito
file2 Only,taro-2.yamada
file2 Only,gou.yamashita
と出力したいのです。

お願いします。

No. 4295 # 68user 2005/09/16 (金) 03:18:00
>>4294 hagu
案1. file1.txt を while で 1行ずつ読み込み、読み込んだ行が
          file2.txt に含まれるかを grep で調べる。
案2. file1.txt と file2.txt をそれぞれ sort し、diff をとって、
          行頭が < か、> かを調べる。重複する行は…どうしましょうねぇ。
案3. perl でハッシュに突っ込む。3行くらいで書けそうな気がします。

No. 4296 # hagu 2005/09/16 (金) 08:40:58
>> 4295

perl使用したことありません。
書くとしたらどうなりますか。

案1ですと、file1.txtで調べたあと、file2.txtのみで存在する物も調べるので
同様の処理が必要になります。重複する行が2回でることになります。

No. 4297 # 68user 2005/09/16 (金) 10:06:43
>>4296 hagu
Perl クックブック VOLUME 1 のレシピ 4.8・4.9 あたりを立ち読みして、
なんとかなりそうなら手を出してみるとよいでしょう。

> 重複する行が2回でることになります。
file2.txt を while で 1行ずつ読み込み、読み込んだ行が file1.txt に
含まれていれば何も表示しない、でいいのでは。

> 案2. file1.txt と file2.txt をそれぞれ sort し、diff をとって、
> 行頭が < か、> かを調べる。重複する行は…どうしましょうねぇ。
GNU diff があるなら (unified diff を出力できる diff があるなら)、
    % diff -u -U 10000 file1.txt file2.txt
として (10000 はファイルの行数を超える数)、
    ・行頭が - なら file1.txt のみ
    ・行頭が + なら file2.txt のみ
    ・行頭がスペースなら重複行
ですかね。

No. 4298 # シャチ 2005/09/17 (土) 11:00:02
>>4294 hagu

1.file1.txtとfile2.txtを辞書順にソートする。
2.diffコマンドで、file1.txtとfile2.txtの差異を表示する。
diffコマンドの出力結果の見方は、ご存じですよね。
">"は、右側に指定したファイル内に差異があることを示す。
"<"は、左側に指定たファイルにある差異があることを示す。

3.grepとかcutを使用して見やすいように編集。
4.file1.txtかfile2.txtをキーにして、grepで存在する文字列だけを抽出。

で、出来ると思います。

No. 4299 # has 2005/09/20 (火) 23:20:36
>>4294 hagu
動作未確認ですが、こういうのはダメですかね。

sort file1 | uniq > file1-2
sort file2 | uniq > file2-2
comm -23 file1-2 file2-2 | sed 's/^/file1 Only,/'
comm -13 file1-2 file2-2 | sed 's/^/file2 Only,/'
comm -12 file1-2 file2-2 | sed 's/^/common,/'

順序よく並んでしまいますが。

Prev< No. 4280〜4299> Next  [最新発言に戻る] [過去ログ一覧]