首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >awk +使用awk和for循环进行组和,用于读取和输出

awk +使用awk和for循环进行组和,用于读取和输出
EN

Stack Overflow用户
提问于 2016-07-29 03:28:50
回答 1查看 36关注 0票数 1

这是我的档案:

代码语言:javascript
复制
$ cat -v  head_datafile_pipe_deleimiter_more_columns.csv
"Rec_Open_Date"|"MSISDN"|"IMEI"|"Data_Volume_Bytes"|"Device_Manufacturer"|"Device_Model"|"Product_Description"|"Data_Volume_MB"|">20MB/30"|">200MB/30"|">2048MB/30"|">5120MB/30"|">10240MB/30"
"2016-07-25"|"537"|"190"|"48195367"|"Samsung Korea"|"Samsung SM-G928I"|"$49.95 Carryover Plan"|"45.9627"|"1"|"1"|"0"|"0"|"0"
"2016-07-25"|"370"|"780"|"92875513"|"Samsung Korea"|"Samsung SM-J500Y"|"$39.95 Plan"|"88.573"|"1"|"1"|"1"|"0"|"0"
"2016-07-25"|"024"|"640"|"35174867"|"Samsung Korea"|"Samsung GT-I9505"|"$29.95 Plan"|"33.5454"|"1"|"1"|"0"|"0"|"0"
"2016-07-25"|"091"|"660"|"0"|"LG Electronics Inc."|"LG LG-D802"|"PREPAY  PLUS - TRIAL - #16"|"0"|"0"|"0"|"0"|"0"|"0"
"2016-07-25"|"706"|"300"|"33352130"|"Apple Inc"|"Apple iPhone 5S A1530"|"PREPAY PLUS - $0 -"|"31.8071"|"1"|"1"|"0"|"0"|"0"
"2016-07-25"|"917"|"350"|"85820068"|"Apple Inc"|"Apple iPhone 6S Plus A1687"|"$39.95 Plan"|"81.8444"|"1"|"1"|"1"|"0"|"0"
"2016-07-25"|"027"|"070"|"9718436"|"Samsung Korea"|"Samsung SM-G900F"|"$29.95 Plan"|"9.26822"|"1"|"1"|"0"|"0"|"0"
"2016-07-25"|"173"|"780"|"19152160"|"Apple Inc"|"Apple iPhone 6S A1688"|"$49.95 Plan"|"18.2649"|"1"|"1"|"0"|"0"|"0"
"2016-07-25"|"685"|"140"|"17443425"|"Apple Inc"|"Apple iPhone 6S Plus A1687"|"$89.95 Plan"|"16.6353"|"1"|"1"|"0"|"0"|"0"

这是我创建的数组

代码语言:javascript
复制
$ mapfile -t u_vals <<<"$(awk -F'|' 'NR>1{print $7}' head_datafile_pipe_deleimiter_more_columns.csv | sort | uniq)"
$ declare -p u_vals
declare -a u_vals='([0]="\"\$29.95 Plan\"" [1]="\"\$39.95 Plan\"" [2]="\"\$49.95 Carryover Plan\"" [3]="\"\$49.95 Plan\"" [4]="\"\$89.95 Plan\"" [5]="\"PREPAY  PLUS - TRIAL - #16\"" [6]="\"PREPAY PLUS - \$0 -\"")'

THis是我想要的输出的一个例子,但是这只是8-9列之和,我想做8-NF列。这不使用for循环。

代码语言:javascript
复制
$ for el in "${u_vals[@]}"; do  awk -F"|" -v q='"' -v j="$el" '
NR>1{if($7 == j) {gsub(/"/,"",$8); sum+=$8; gsub(/"/,"",$9); sum2+=$9} }; NR>1{count++} END { print "output" FS j FS q count q FS sum FS sum2}' head_datafile_pipe_deleimiter_more_columns.csv; done | cat -n
     1  output|"$29.95 Plan"|"9"|42.8136|2
     2  output|"$39.95 Plan"|"9"|170.417|2
     3  output|"$49.95 Carryover Plan"|"9"|45.9627|1
     4  output|"$49.95 Plan"|"9"|18.2649|1
     5  output|"$89.95 Plan"|"9"|16.6353|1
     6  output|"PREPAY  PLUS - TRIAL - #16"|"9"|0|0
     7  output|"PREPAY PLUS - $0 -"|"9"|31.8071|1

但是我想为cols 8-NF创建一个for循环,我在这里尝试为col8-9 {for(i=8;i<=9;i++) gsub(/"/,"",$i); sum[i]+=$i}创建一个for循环,但我不确定是否可以这样做。

代码语言:javascript
复制
$ for el in "${u_vals[@]}"; do  awk -F"|" -v q='"' -v j="$el" '
NR>1{if($7 == j) {for(i=8;i<=9;i++) gsub(/"/,"",$i); sum[i]+=$i} }; NR>1{count++} END { for(i=8;i<=9;i++) print "output" FS j FS q count q FS sum[i] FS sum[i]}' head_datafile_pipe_deleimiter_more_columns.csv; done | cat -n

这是我想要的输出,这里只有cols 8和9分组的总和:

代码语言:javascript
复制
........................|col8   |col9|...

output|"$29.95 Plan"|"9"|42.8136|2|<other column sums here>
output|"$39.95 Plan"|"9"|170.417|2 ...
output|"$49.95 Carryover Plan"|"9"|45.9627|1
output|"$49.95 Plan"|"9"|18.2649|1
output|"$89.95 Plan"|"9"|16.6353|1
output|"PREPAY  PLUS - TRIAL - #16"|"9"|0|0
output|"PREPAY PLUS - $0 -"|"9"|31.8071|1|<other column sums here>

EDIT1

试图理解printprintf之间的区别,这是我的发挥,这是有帮助的。

以下两个命令之间的唯一区别是:

print ("output" FS j FS q count q FS sum[8]);

printf ("output" FS j FS q count q FS sum[8]);

代码语言:javascript
复制
$ for el in "${u_vals[@]}"; do  awk -F"|" -v q='"' -v j="$el" '
NR>1{if($7 == j) {for(i=8;i<=NF;i++){gsub(/"/,"",$i); sum[i]+=$i}} }; NR>1{count++} END { print ("output" FS j FS q count q FS sum[8]); for(i=8;i<=NF; i++){ printf("%s",FS sum[i])} printf("\n")}' head_datafile_pipe_deleimiter_more_columns.csv; done | cat -n
     1  output|"$29.95 Plan"|"9"|42.8136
     2  |42.8136|2|2|0|0|0
     3  output|"$39.95 Plan"|"9"|170.417
     4  |170.417|2|2|2|0|0
     5  output|"$49.95 Carryover Plan"|"9"|45.9627
     6  |45.9627|1|1|0|0|0
     7  output|"$49.95 Plan"|"9"|18.2649
     8  |18.2649|1|1|0|0|0
     9  output|"$89.95 Plan"|"9"|16.6353
    10  |16.6353|1|1|0|0|0
    11  output|"PREPAY  PLUS - TRIAL - #16"|"9"|0
    12  |0|0|0|0|0|0
    13  output|"PREPAY PLUS - $0 -"|"9"|31.8071
    14  |31.8071|1|1|0|0|0
1415137039 [main] -sh 4624 sig_send: error sending signal -66, pipe handle 0x1210, nb 132, packsize 0, Win32 error 0

$ for el in "${u_vals[@]}"; do  awk -F"|" -v q='"' -v j="$el" '
NR>1{if($7 == j) {for(i=8;i<=NF;i++){gsub(/"/,"",$i); sum[i]+=$i}} }; NR>1{count++} END { printf ("output" FS j FS q count q FS sum[8]); for(i=8;i<=NF; i++){ printf("%s",FS sum[i])} printf("\n")}' head_datafile_pipe_deleimiter_more_columns.csv; done | cat -n
     1  output|"$29.95 Plan"|"9"|42.8136|42.8136|2|2|0|0|0
     2  output|"$39.95 Plan"|"9"|170.417|170.417|2|2|2|0|0
     3  output|"$49.95 Carryover Plan"|"9"|45.9627|45.9627|1|1|0|0|0
     4  output|"$49.95 Plan"|"9"|18.2649|18.2649|1|1|0|0|0
     5  output|"$89.95 Plan"|"9"|16.6353|16.6353|1|1|0|0|0
     6  output|"PREPAY  PLUS - TRIAL - #16"|"9"|0|0|0|0|0|0|0
     7  output|"PREPAY PLUS - $0 -"|"9"|31.8071|31.8071|1|1|0|0|0
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-07-29 04:08:45

您可以简单地将8次迭代到NF。还必须将END块中的最后一个printf调用替换为一个初始printf,以打印在8:NF字段之前要输出的字段,然后在for-循环中使用printf调用打印8:NF字段,最后在for-循环之后打印换行符。对于前两次打印,我们必须使用printf而不是print,以防止换行符过早打印。

代码语言:javascript
复制
for el in "${u_vals[@]}"; do

    awk -F\| -v q=\" -v j="$el" '

        NR > 1 {
            if ($7 == j) {
                for (i = 8; i <= NF; ++i) {
                    gsub(/"/,"",$i);
                    sum[i] += $i;
                }
            }
            ++count;
        };

        END {
            printf("%s","output" FS j FS q count q);
            for (i = 8; i <= NF; ++i)
                printf("%s",FS sum[i]);
            printf("\n");
        };

    ' head_datafile_pipe_deleimiter_more_columns.csv;

done| cat -n;
##      1  output|"$29.95 Plan"|"9"|42.8136|2|2|0|0|0
##      2  output|"$39.95 Plan"|"9"|170.417|2|2|2|0|0
##      3  output|"$49.95 Carryover Plan"|"9"|45.9627|1|1|0|0|0
##      4  output|"$49.95 Plan"|"9"|18.2649|1|1|0|0|0
##      5  output|"$89.95 Plan"|"9"|16.6353|1|1|0|0|0
##      6  output|"PREPAY  PLUS - TRIAL - #16"|"9"|0|0|0|0|0|0
##      7  output|"PREPAY PLUS - $0 -"|"9"|31.8071|1|1|0|0|0
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38650072

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档