【问题标题】:Parsing a .csv-like file in bash在 bash 中解析类似 .csv 的文件
【发布时间】:2015-12-04 12:51:15
【问题描述】:

我有一个格式如下的文件:

string1,string2,string3,...
...

我必须分析第二列,计算每个字符串的出现次数,并生成一个格式如下的文件:

"number of occurrences of x",x
"number of occurrences of y",y        
...

我设法编写了以下脚本,效果很好:

#!/bin/bash

> output
regExp='^\s*([0-9]+) (.+)$'
while IFS= read -r line
do
    if [[ "$line" =~ $regExp ]]
    then
        printf "${BASH_REMATCH[1]},${BASH_REMATCH[2]}\n" >> output
    fi
done <<< "`gawk -F , '!/^$/ {print $2}' $1 | sort | uniq -c`"

我的问题是: 有更好更简单的方法来完成这项工作吗?

特别是我不知道如何解决这个问题:

gawk -F , '!/^$/ {print $2}' miocsv.csv | sort | uniq -c | gawk '{print $1","$2}'

问题是 string2 可以包含空格,如果是这样,gawk 上的第二次调用将截断字符串。 我都不知道如何打印“从 2 到 NF”的所有字段,保持分隔符,这可以连续出现多次。

非常感谢, 再见

编辑:

如题,这里有一些示例数据:

(这是一个练习,对发明者感到抱歉)

输入:

*,*,*
test,  test  ,test
prova, * , prova
test,test,test
prova,  prova   ,prova
leonardo,da vinci,leonardo
in,o    u   t   ,pr
, spaces ,
, spaces ,
leonardo,da vinci,leonardo
leonardo,da vinci,leonardo
leonardo,da vinci,leonardo
in,o    u   t   ,pr
test,  test  ,test
,   tabs    ,
,   tabs    ,
po,po,po
po,po,po
po,po,po
prova, * , prova
prova, * , prova
*,*,*
*,*,*
*,*,*
, spaces ,
,   tabs    ,

输出:

3, * 
4,*
4,da vinci
2,o u   t   
3,po
1,  prova   
3, spaces 
3,  tabs    
1,test
2,  test  

【问题讨论】:

    标签: regex bash csv awk gawk


    【解决方案1】:

    awk 中的单行代码:

    awk -F, 'x[$2]++ { } END { for (i in x) print x[i] "," i }' input.csv
    

    它将每个第二列字符串的计数存储在关联数组x 中,最后循环遍历数组并打印结果。

    要获得您为本示例显示的确切输出,您需要将其通过管道传输到 sort(1),将字段分隔符设置为 ,,并将排序键设置为第二个字段:

    awk -F, 'x[$2]++ { } END { for (i in x) print x[i] "," i }' input.csv | sort -t, -k2,2
    

    当然,唯一的条件是每行的第二列不包含,

    【讨论】:

    • 谢谢!不幸的是,我不擅长 awk... 它的功能令人难以置信
    • @Nopaste 确实,它是一个非常强大的工具。如果您有时间,我建议您阅读awk 编程语言,它会教您这个(以及更多)。
    【解决方案2】:

    您可以制作最终的 awk:

    gawk '{ sub(" *","",$0); sub(" ",",",$0); print }'
    

    或将 sed 用于此类事情:

    sed 's/ *\([0-9]*\) /\1,/'
    

    【讨论】:

    • 谢谢.. 我想我会去 sed 版本,似乎是最简单的方法!
    • 我只做了一点改动:sed -r 's/^ *([0-9]+) /\1,/'
    【解决方案3】:

    这是一个 Perl 单行,类似于 Filipe 的 awk 解决方案:

    perl -F, -lane '$x{$F[1]}++; END{ for $i (sort keys %x) { print "$x{$i},$i" } }' input.csv
    

    输出根据第二列按字母顺序排序。
    @F 自动拆分数组从索引 $F[0] 开始,而 awk 字段以 $1 开始

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-16
      • 2013-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-13
      相关资源
      最近更新 更多