我有单独行的文本,每行都有类似CSV的格式:
SOME BUNCH OF TEXT, FIELD_A: 12, FIELD_B: 0.2321, FIELD_C: 12:10:08 2011/07/22, FIELD_D: 656
字段的顺序始终相同,但某些字段可能不存在。在感兴趣的字段之间可以有其他字段,例如,与上面的行相比,我也可以获得以下内容:
SOME BUNCH OF TEXT, FIELD_A: 12, NOT_INTERESTED: 235, FIELD_B: 0.2321, FIELD_C: 12:10:08 2011/07/22, FIELD_D: 656, FIELDS
作为处理此文本的结果,我希望有一个干净的CSV文件,我的字段一个接一个地指定:
12,0.2321,12:10:08 2011/07/22,656
如果某个字段不存在,那么我想简单省略值(例如FIELD_B不存在):
12,,12:10:08 2011/07/22,656
如何使用sed,perl或awk等命令执行此操作?
我尝试使用perl -pe 's/^.*?(FIELD_A: (.*?),)?.*?$/\2/'
提取单个字段并失败 - 正则表达式只是忽略了我的字段,即使它出现
答案 0 :(得分:2)
您可以将awk
与关联数组一起使用,如下所示。遍历字段并在:
上拆分它们。然后将键值对存储到关联数组中。最后打印出你想要的字段。
awk -F, '{
split("",arr)
for(i=1; i<=NF; i++){
a=index($i, ":")
if(a != 0){
# split on first colon to get key-value pair
key=substr($i,1,a-1)
val=substr($i,a+1)
# remove leading spaces from key and value
gsub(/^ */,"",key)
gsub(/^ */,"",val)
# store in an associative array
arr[key]=val
}
}
# print out the desired fields
print arr["FIELD_A"]","arr["FIELD_B"]","arr["FIELD_C"]","arr["FIELD_D"]
}' data.txt
答案 1 :(得分:1)
这种方式怎么样(假设已知文件名):
#!/usr/bin/perl
use strict;
use warnings;
my @f = qw(FIELD_A FIELD_B FIELD_C FIELD_D);
while(my $line = <DATA>) {
chomp $line;
my @r;
for(@f) {
if ($line =~ /$_:\s*([^,]+)/) {
push @r, $1;
} else {
push @r,'';
}
}
print join(',',@r), "\n";
}
__DATA__
SOME BUNCH OF TEXT, FIELD_A: 12, FIELD_B: 0.2321, FIELD_C: 12:10:08 2011/07/22, FIELD_D: 656
SOME BUNCH OF TEXT, FIELD_A: 12, NOT_INTERESTED: 235, FIELD_B: 0.2321, FIELD_C: 12:10:08 2011/07/22, FIELD_D: 656, FIELDS
SOME BUNCH OF TEXT, FIELD_A: 12, NOT_INTERESTED: 235, FIELD_C: 12:10:08 2011/07/22, FIELD_D: 656, FIELDS
<强>输出:强>
12,0.2321,12:10:08 2011/07/22,656
12,0.2321,12:10:08 2011/07/22,656
12,,12:10:08 2011/07/22,656