Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 在bash中解析类似.csv的文件_Regex_Bash_Csv_Awk_Gawk - Fatal编程技术网

Regex 在bash中解析类似.csv的文件

Regex 在bash中解析类似.csv的文件,regex,bash,csv,awk,gawk,Regex,Bash,Csv,Awk,Gawk,我有一个格式如下的文件: string1,string2,string3,... ... "number of occurrences of x",x "number of occurrences of y",y ... 我必须分析第二列,计算每个字符串的出现次数,并生成一个格式如下的文件: string1,string2,string3,... ... "number of occurrences of x",x "number of occurrences of y",

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

string1,string2,string3,...
...
"number of occurrences of x",x
"number of occurrences of y",y        
...
我必须分析第二列,计算每个字符串的出现次数,并生成一个格式如下的文件:

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`"
问题是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  

您可以进行最后的awk:

gawk '{ sub(" *","",$0); sub(" ",",",$0); print }'
或者将sed用于这类事情:

sed 's/ *\([0-9]*\) /\1,/'
awk中的一个班轮:

awk -F, 'x[$2]++ { } END { for (i in x) print x[i] "," i }' input.csv
它将每个第二列字符串的计数存储在关联数组
x
中,并在末尾循环数组并打印结果

要获得本例中显示的准确输出,您需要将其输送到
排序(1)
,将字段分隔符设置为
,并将排序键设置为第二个字段:

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

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

这里有一个Perl one liner,类似于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

开始,谢谢!不幸的是我不擅长awk。。。它所能做到的真是难以置信do@Nopaste事实上,它是一个非常强大的工具。如果您有时间,我建议您阅读awk编程语言,它将教会您这一点(以及更多)。谢谢。。我想我会选择sed版本,这似乎是最简单的方法!我只做了一点修改:
sed-r的/^*([0-9]+)/\1,/'