• ベストアンサー

Linuxシェルによる同一文字列のカウント集計

あるファイル中の同じ文字列の行をカウントして それぞれの文字列が何回現れるか集計するシェルを作ろうとしています。 しかし、最後のグループの集計がうまくいきません。 入力ファイルはソート済みです。 スコープの問題なのかどうか良くわかりませんが、想定外の動きをします。 このシェルの修正もしくは、別のいい集計方法、 どちらでも歓迎です。よろしくお願いします。 書いてみたシェル ------------------ #!/bin/sh TARGET_STR=`head -n 1 uniqData.txt` declare -i COUNT=0 cat uniqData.txt | while read LINE_STR do if [ "${TARGET_STR}" = "${LINE_STR}" ]; then COUNT=$COUNT+1 else echo $TARGET_STR:$COUNT TARGET_STR=${LINE_STR} COUNT=1 fi done echo $TARGET_STR:$COUNT ------------------ 入力ファイル ------------------ asd asd asd dfg dfg gghhjj gghhjj gghhjj gghhjj ttyyuuu ttyyuuu ttyyuuu wwee ------------------ 期待出力 ------------------ asd:3 dfg:2 gghhjj:4 ttyyuuu:3 wwee:1 ------------------ 実際の出力 ------------------ asd:3 dfg:2 gghhjj:4 ttyyuuu:3 asd:0 ------------------

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

  • ベストアンサー
  • OKwebb
  • ベストアンサー率44% (92/208)
回答No.2

回答としては#1の方法がベストだと思います。 参考までにシェルが希望通りに動作しないのは、 パイプ以降がサブシェルで動作するからです。 多分asdの行数が1行のときもうまくいかないのではないでしょうか? 解決方法としては以下のいずれかが考えられます。 1.変数をexportしてしまう。 2.シェルをbashに変更してwhileの部分も変更する。 while read LINE_STR do 省略 done < uniqData.txt 3.シェルをkshとかに変更。

mibusys
質問者

お礼

>パイプ以降がサブシェルで動作するからです。 おぉ。なるほど。非常に勉強になります。 方法としては#1の方が紹介してくださった方法で行いますが、 まだわかっていないことが多いので、こういう情報は非常に助かります。 ありがとうございます。

その他の回答 (2)

  • Toshi0230
  • ベストアンサー率51% (836/1635)
回答No.3

基本的にNo.1さんの回答で終わっちゃうんですが、少し補足。 データファイルがソートされていなくても % sort uniqData.txt | uniq -c でできますね。 出力形式が期待と違うでしょうけど、そこはawkなりperlなりで整形してください。

mibusys
質問者

お礼

整形は大丈夫です。 ありがとうございました。

  • t-okura
  • ベストアンサー率75% (253/335)
回答No.1

cat uniqData.txt | uniq -c

参考URL:
http://www.linux.or.jp/JM/html/gnumaniak/man1/uniq.1.html
mibusys
質問者

お礼

うわぁ。素人丸出しですね。ちょっと恥ずかしいです。 uniqは知っていたのですが、こんなオプションもあるんですね。 こちらの方法を利用して実装します。 大変助かりました。ありがとうございました。

関連するQ&A

  • 文字列をカウントするにはどうすればいいのでしょうか?

    ファイル読み込み後その中の特定の文字列、「映画」の個数をカウントするというプログラムを次のように作ってみましたが、実際に起動してみるとエラーになります。何かわかる方がいれば教えてください。 #!/usr/local/bin/perl if (open(FH, "data/log.txt")) { @file = <FH>; close(FH); } foreach $count (@file){ $count = ($line =~ tr/映画/映画/); } print $count; exit;

    • ベストアンサー
    • CGI
  • シェルスクリプト

    2月14日頃質問のあった”UNIXのシェルスクリプトを使用してテキストファイルのある列にある特定の文字列を条件としてその行を出力するということをやりたい”を下記のように作ってみました。問題ないか逆質問の形で投稿します。(ルール違反かもしれませんが質問が締め切られているので・・・) #!/bin/bash CAT=YAHOO while read LINE do echo $LINE > tmp.txt DOG=`cut -d" " -f2 tmp.txt` if [ "$CAT" = "$DOG" ] then echo "$LINE" fi done < catalog.file

  • 文字列中に含まれる文字の個数をカウントするプログラムについて…

    文字列、1文字が与えられたとき、これをポインタで入力し文字列中に含まれる文字の個数を計算するプログラムを作成せよ。 と、いう課題がだされたんですけど、ユーザが任意の文字列と1文字を入力できるようにすることができません…。 多分main関数の部分をちょっといじくればよいと思うのですが…。 どなたかアドバイスをお願いします。 #include <stdio.h> int count(const char *str, const char ch) { int cnt=0; while (*str!='\0') { if (*str==ch) cnt++; str++; } return cnt; } int main() { const char *str="hello,world!"; const ch='o'; int cnt; cnt=count(str, ch); printf("%s中に%cは%d個です\n", str, ch, cnt); return 0; }

  • シェル関数引数のスペース文字列をgrepに

    下記のシェル関数 arg_space() 内で、grepを使いたいのですが。 'aaa bbb' などのスペースを含む文字列を引数として渡すとスペース後の文字列がファイル名と 認識されてしまいます。 -- arg_space.sh -- #!/bin/bash CHK_STR='aaa bbb' FILE_NAME='data/aaa.txt' function arg_space() { return `grep -c $1 $2` } arg_space $CHK_STR $FILE_NAME if [ $? -ge 1 ]; then echo 'Match !!' else echo 'No match.' fi exit 0 ------------------ ]# ./arg_space.sh grep: bbb: No such file or directory Match !! スペース文字を、grep に区切り文字として認識させないようにする 方法を教えて 頂けないでしょうか。 -- data/aaa.txt -- aaa bbb ccc ddd ---------------

  • awkで列を集計するシェルについて

    シェル初心者です。教えてください。 ログファイルが10万行超えるものでシェルにて集計することになり、下記のような集計ができればと思っています。 商店名 商品名  価格 A商店 りんご   100 B商店  ぶどう 300 A商店  みかん 150 C商店  りんご 100 A商店  りんご 100 B商店  みかん 150 C商店  りんご 100 C商店  ぶどう 300 ※各列はブランク(空白)によって区切られ、改行済みで行数は10万行以上 (1)awk '{print $1}' | uniq -d (重複した商店の抽出) (2)awk '{print $2}' | uniq -d (重複した商品名の抽出) (1)、(2)の抽出を満たす「価格」の合計を"集計結果”として > shukei.txt などに出力したいと思ってます。 VBAでいれば、firlterしsumifして合計するようなイメージのものです。 ご教授お願い致します><

  • Kシェル上でフラットファイルの条件付き集計をしたい。

    いつもお世話になっています。Kornシェルで、以下のようなcsv形式のファイルを次の様に集計したいです。 <列A,C,D,E,F,G が全て一致する行毎に列Fの値を集計> (入力) 列A------列B------列C----列D---列E--列F-----列G------列F "10001","0090300", 11110," "," "," "," ",1013134 "10001","0090300", 11130,"0009","888","01","5050455",28428260 "10001","0090300", 11130,"0001","001","01","1111111",258925 "10001","0090300", 11165,"9900","999","09","9999903",0 "10001","0090300", 11110," "," "," "," ",592092 "10001","0090400", 11130,"0009","129","01","1018224",12489867 "10001","0090300", 11130,"0001","001","01","1111111",200000 "10001","0090400", 11165,"9900","999","09","9999904",834592 "10001","0090700", 11110," "," "," "," ",300000 (期待する出力) "10001","0090300", 11110," "," "," "," ",1905226 <--- 1行目, 5行目, 9行目が集計されている "10001","0090300", 11130,"0009","888","01","5050455",28428260 "10001","0090300", 11130,"0001","001","01","1111111",458925 <--- 3行目と7行目が集計されている "10001","0090300", 11165,"9900","999","09","9999903",0 "10001","0090400", 11165,"9900","999","09","9999904",834592 "10001","0090400", 11130,"0009","129","01","1018224",12489867 出力のソートの必要はありません。 これをシェル・スクリプトだけで実装するのは、無理でしょうか。良いアイディアをお願いします。

  • シェルスクリプト文字列の処理について

    はじめましてよろしくお願いします。 質問サイトもシェルも初心者なので至らない点がございましたら ご容赦の程よろしくお願いします。 下記シェルスクリプトを実行すると下記エラーが発生します。 「test2」変数に空白無しで「abc」と入力するとエラーは発生しません。 変数test2の値(a bc)を変更せずにエラーが発生しない方法はないでしょうか? 手段でもかまいませんので教えてください。 ========================= testsh110207.sh ====================================== #!/bin/sh test1="abc" test2="a bc" if [ ${test1} = ${test2} ] then echo "=:文字列1と文字列2が等しい場合に真" echo "test1の「${test1}」と、test2の「${test2}」は等しい" fi if [ ${test1} != ${test2} ] then echo "!=:数値1と数値2が等しくない場合に真" echo "test1の「${test1}」と、test2の「${test2}」は等しくない" fi echo "********* テスト完了 *********" ======================================================================= $ ./testsh110207.sh ./testsh110207.sh: line 6: [: too many arguments ./testsh110207.sh: line 13: [: too many arguments ********* テスト完了 *********

  • Cシェルで、文字列中(str)に、固定文字列(abc)の数を数える方法

    Cシェルで、文字列中(str)に、固定文字列(abc)の数を数える方法を教えてください たとえば、 set str = abcdabceabcd set abc = abc str中に、abcを現れる数(3)を求める方法を教えてください Cシェルは詳しい方がいらっしゃいましたら、是非教えてお願いいたします

    • ベストアンサー
    • AJAX
  • シェルスクリプトでファイル内の数値文字列を数値として扱うには

    失礼します。 シェルスクリプトでファイル内のテキスト(数値文字列)を取得して、それを使って計算するにはどうすれば良いでしょうか? str:ファイル内のテキスト(数値文字列) res=$(( $str + 1 )) ・エラー ")syntax error: invalid arithmetic operator (error token is " よろしくお願いします。

  • シェルでファイルを読み込み、そのレコードを分解し、分解した文字列を使用

    シェルでファイルを読み込み、そのレコードを分解し、分解した文字列を使用してコマンドを発行したい。 ■処理内容 下記のファイルを読み込み、aaa=○○の○○を使用してコマンドを発行したいです。 ■理解している所 & 質問 ファイルを引数に起動し、配列として取得 str=`cut -f 1 -d ',' $1 | cut -c 8-` ループで回して値を一個一個取り出して実行 i=0 while [ $i < ${#str[@]} ];do echo $str[$i] i = $i + 1 done なんとなくできるような気はしているのですが、 cutでstr変数に入れた所で一つの文字列と入ってしまっているようで、 正しくループが回せません。(分解した後にecho "${str[1]}" echo "${str[2]}"] などと実行しても空です) 完全案を教えてください。 ■ファイル aaaaaaa=testdata1,bbb=testdata2,ccc=testdata3 aaaaaaa=hhogedata1,bbb=hugahugadata2,ccc=piyopiyodata3 ※aaa=○○,bbb=××,ccc=△△という形式で、各○○の部分の長さは不定。 ※レコード数は不定。