Chinaunix

标题: 求助大神,多文本统计 [打印本页]

作者: CDX0923    时间: 2019-01-03 19:03
标题: 求助大神,多文本统计
求助大神,统计多个文件关键字出现的次数,请大神指教如何实现,内容如下:
file1
洲,国,省,市,a
亚洲,中国,宁夏,银川,fsaf
亚洲,中国,辽宁,沈阳,gag
亚洲,中国,河北,石家庄,sgag
亚洲,中国,陕西,西安,eyy
亚洲,中国,陕西,西安,xv

file2
洲,国,省,市,b
亚洲,中国,辽宁,沈阳,xcv
亚洲,中国,宁夏,银川,kryh
亚洲,中国,陕西,西安,la
亚洲,中国,河南,郑州,pwej



file3
洲,国,省,市,c
亚洲,中国,陕西,西安,wow
亚洲,中国,河北,石家庄,cfg
亚洲,中国,甘肃,兰州,cnf
亚洲,中国,陕西,西安,aaww



统计想要的结果
洲,国,省,市,file1,file2,file3
亚洲,中国,宁夏,银川,1,1,0
亚洲,中国,辽宁,沈阳,1,1,0
亚洲,中国,河北,石家庄,1,0,1
亚洲,中国,陕西,西安,2,1,2
亚洲,中国,河南,郑州,0,1,0
亚洲,中国,甘肃,兰州,0,0,1


作者: csccyab    时间: 2019-01-09 16:09
本帖最后由 csccyab 于 2019-01-09 16:13 编辑

$ awk -F',' 'FNR>1{a[$1,$2,$3,$4]} FILENAME==ARGV[1]&&FNR>1{a1[$1,$2,$3,$4]++} FILENAME==ARGV[2]&&FNR>1{a2[$1,$2,$3,$4]++} FILENAME==ARGV[3]&&FNR>1{a3[$1,$2,$3,$4]++}END{for (i in a) {split(i,b,SUBSEP); printf "%s,%s,%s,%s,%d,%d,%d\n",b[1],b[2],b[3],b[4],a1,a2,a3}} ' file1 file2 file3
亚洲,中国,河北,石家庄,1,0,1
亚洲,中国,陕西,西安,2,1,2
亚洲,中国,宁夏,银川,1,1,0
亚洲,中国,甘肃,兰州,0,0,1
亚洲,中国,河南,郑州,0,1,0
亚洲,中国,辽宁,沈阳,1,1,0

作者: CDX0923    时间: 2019-01-10 11:09
回复 2# csccyab

这个我执行之后报错 awk: cmd. line:1: (FILENAME=file3 FNR=5) fatal: attempt to use array `a1' in a scalar context
作者: CDX0923    时间: 2019-01-10 11:09
回复 2# csccyab

这个我执行之后报错 awk: cmd. line:1: (FILENAME=file3 FNR=5) fatal: attempt to use array `a1' in a scalar context
作者: CDX0923    时间: 2019-01-10 11:10
本帖最后由 CDX0923 于 2019-01-10 11:12 编辑

回复 2# csccyab

论坛报错就多出现了几条回复
作者: csccyab    时间: 2019-01-10 14:01
This should be correct:

awk -F',' 'FNR>1{a[$1,$2,$3,$4]} FILENAME==ARGV[1]&&FNR>1{a1[$1,$2,$3,$4]++} FILENAME==ARGV[2]&&FNR>1{a2[$1,$2,$3,$4]++} FILENAME==ARGV[3]&&FNR>1{a3[$1,$2,$3,$4]++}END{for (i in a) {split(i,b,SUBSEP); printf "%s,%s,%s,%s,%d,%d,%d\n",b[1],b[2],b[3],b[4],a1[i],a2[i],a3[i]}} ' file1 file2 file3
作者: CDX0923    时间: 2019-01-10 17:29
csccyab 发表于 2019-01-10 14:01
This should be correct:awk -F',' 'FNR>1{a[$1,$2,$3,$4]} FILENAME==ARGV[1]&&FNR>1{a1[$1,$2,$3,$4]++}  ...

可以了,谢谢大神

作者: CDX0923    时间: 2019-01-11 10:27
回复 6# csccyab

如果是几十个文件的话这个有优化的写法吗
作者: csccyab    时间: 2019-01-11 17:16
本帖最后由 csccyab 于 2019-01-24 20:59 编辑

Python 版本

$ cat 3.py
import collections, sys, re

filecount=0
dict1 = collections.defaultdict(list)

for file1 in sys.argv[1:]:
   filecount+=1
   f = open(file1, "r")
   linecount=1
   for line in f:
      if linecount>1:
         p = re.search("^(.+),.+", line.strip())
         if p:
            dict1[p.group(1)].append(filecount)
      linecount+=1

for the_key, the_value in dict1.iteritems():
   count=''
   sys.stdout.write(the_key + ',')
   c = collections.Counter(the_value)
   for i in range(1,filecount+1):
      if count:
         count = count + "," + str(c)
      else:
         count = str(c)
   print(count)


$ python 3.py file1 file2 file3
亚洲,中国,辽宁,沈阳,1,1,0
亚洲,中国,陕西,西安,2,1,2
亚洲,中国,甘肃,兰州,0,0,1
亚洲,中国,河南,郑州,0,1,0
亚洲,中国,宁夏,银川,1,1,0
亚洲,中国,河北,石家庄,1,0,1



作者: csccyab    时间: 2019-01-24 15:06
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <regex.h>
  4. #include <string.h>

  5. struct LinkedList {
  6.         int* count;
  7.         char* data;
  8.         struct LinkedList *next;
  9. };

  10. typedef struct LinkedList *node;

  11. int main(int argc, char *argv[]) {
  12.         int i;
  13.         FILE *f;
  14.         char line[30];
  15.         const char* pattern = "(.+),.+";
  16.         node head = NULL;
  17.         int linecount;
  18.         char firstline[30];

  19.         regex_t preg;
  20.         regmatch_t pmatch[50];
  21.         regcomp(&preg, pattern, REG_EXTENDED);


  22.         for (i=1; i<argc; i++) {
  23.                 f = fopen(argv, "r");
  24.                 linecount = 0;
  25.                 if (f == NULL){
  26.                         printf("Can't open file %s", argv);
  27.                         exit(1);
  28.                 }
  29.                 int r=0;
  30.                 while (fscanf(f, "%s", line) == 1) {
  31.                         linecount++;
  32.                         if (linecount > 1) {
  33.                                 if (!regexec(&preg, line, 3, pmatch, 0)) {
  34.                                         if (head == NULL){
  35.                                                 head = (node)malloc(sizeof(struct LinkedList));
  36.                                                 head->data = malloc(50);
  37.                                                 head->next = NULL;
  38.                                                 strncpy(head->data, line + pmatch[1].rm_so, pmatch[1].rm_eo - pmatch[1].rm_so);
  39.                                                 head->count = (int*)calloc(argc-1, sizeof(int));
  40.                                                 head->count[i-1]++;
  41.                                         } else {
  42.                                                 node temp, p;
  43.                                                 p = head;

  44.                                                 temp = (node)malloc(sizeof(struct LinkedList));
  45.                                                 temp->data = malloc(50);
  46.                                                 temp->next = NULL;
  47.                                                 temp->count = (int*)calloc(argc-1, sizeof(int));
  48.                                                 temp->count[i-1] = 1;
  49.                                                 strncpy(temp->data, line + pmatch[1].rm_so, pmatch[1].rm_eo - pmatch[1].rm_so);

  50.                                                 while(1){
  51.                                                         int res = strcmp(temp->data, p->data);
  52.                                                         if (res==0) {
  53.                                                                 p->count[i-1]++;
  54.                                                                 break;
  55.                                                         } else {
  56.                                                                 if (p->next == NULL) {
  57.                                                                         p->next = temp;
  58.                                                                         break;
  59.                                                                 }
  60.                                                         }
  61.                                                         p = p->next;
  62.                                                 }
  63.                                         }
  64.                                 }
  65.                         } else {
  66.                                 regexec(&preg, line, 3, pmatch, 0);
  67.                                 strncpy(firstline, line + pmatch[1].rm_so, pmatch[1].rm_eo - pmatch[1].rm_so);
  68.                         }
  69.                 }
  70.                 fclose(f);
  71.         }

  72.         node ptr = head;

  73.         printf("%s", firstline);
  74.         for (i=1; i<argc; i++)
  75.                 printf(",%s", argv);
  76.         printf("\n");

  77.         while (ptr != NULL){
  78.                 printf("%s", ptr->data);
  79.                 int j;
  80.                 for (j=0; j<argc-1; j++)
  81.                         printf(",%d", ptr->count[j]);
  82.                 printf("\n");
  83.                 ptr = ptr->next;
  84.         }
  85. }
复制代码


$ ./ll 1.txt 2.txt 3.txt
洲,国,省,市,1.txt,2.txt,3.txt
亚洲,中国,宁夏,银川,1,1,0
亚洲,中国,辽宁,沈阳,1,1,0
亚洲,中国,河北,石家庄,1,0,1
亚洲,中国,陕西,西安,2,1,2
亚洲,中国,河南,郑州,0,1,0
亚洲,中国,甘肃,兰州,0,0,1


作者: csccyab    时间: 2019-01-24 15:10
以上是 C 版本。
因為 C 沒有 associative array,
所以用了 linked list 去儲存數据

寫得不好欢迎糾正

作者: klainogn    时间: 2019-01-24 19:09
  1. BEGIN{
  2.     FS=","
  3. }
  4. FNR==1{
  5.     headline=$1","$2","$3","$4
  6.     filelist[fileindex++]=FILENAME
  7. }
  8. FNR>1{
  9.     a[$1","$2","$3","$4][FILENAME]++
  10. }
  11. END{
  12.     for(i in a){
  13.         str=i
  14.         for(j in filelist){
  15.             str=str","(+a[i][filelist[j]])
  16.         }
  17.         print str
  18.     }
  19. }
  20. $ awk -f test.awk 1.txt 2.txt 3.txt
  21. 亚洲,中国,河北,石家庄,1,0,1
  22. 亚洲,中国,辽宁,沈阳,1,1,0
  23. 亚洲,中国,陕西,西安,2,1,2
  24. 亚洲,中国,宁夏,银川,1,1,0
  25. 亚洲,中国,甘肃,兰州,0,0,1
  26. 亚洲,中国,河南,郑州,0,1,0
复制代码


作者: csccyab    时间: 2019-01-31 10:26
本帖最后由 csccyab 于 2019-01-31 10:30 编辑

C++ 版本, 寫了這麼多, 不知樓主有沒有試



  1. #include <iostream>
  2. #include <map>
  3. #include <string>
  4. #include <iterator>
  5. #include <fstream>
  6. #include <regex>

  7. using namespace std;

  8. int main(int argc, char **argv){
  9.         map<string, int*> map1;
  10.         string line, firstline;
  11.         regex preg("(.+),.+");
  12.         smatch match;
  13.         map<string, int*>::iterator itr;
  14.         int linecount = 0;

  15.         for (int i=1; i<argc; ++i){
  16.                 linecount = 0;
  17.                 ifstream f(argv[i]);
  18.                 while (getline(f, line)){
  19.                         linecount++;
  20.                         if (linecount != 1){
  21.                                 if (regex_search(line, match, preg)){
  22.                                         if (map1.count(match.str(1)) == 0) {
  23.                                                 int *count = new int[argc-1]();
  24.                                                 map1[match.str(1)]=count;
  25.                                                 map1[match.str(1)][i-1]=1;
  26.                                         } else
  27.                                                 map1[match.str(1)][i-1]++;
  28.                                 }
  29.                         } else {
  30.                                 if (regex_search(line, match, preg))
  31.                                         firstline = match.str(1);
  32.                         }
  33.                 }
  34.                 f.close();
  35.         }

  36.         cout << firstline;
  37.         for (int i=1; i<argc; ++i)
  38.                 cout << "," << argv[i];
  39.         cout << endl;
  40.         for (itr=map1.begin(); itr!=map1.end(); itr++){
  41.                 cout << itr->first;
  42.                 for (int j=0; j<argc-1; j++)
  43.                         cout << "," << itr->second[j];
  44.                 cout << endl;
  45.         }
  46. }



复制代码





欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2