使用Linux命令进行复杂的CSV解析
我有一个CSV日志文件,记录属性使用Linux命令进行复杂的CSV解析,csv,awk,sed,command-line,Csv,Awk,Sed,Command Line,我有一个CSV日志文件,记录属性HA;血红蛋白;HC;高清;他。以下文件记录了6个条目(由上面的标题分隔) 我想提取每个条目的第三个属性(HC) HA;HB;HC;HD;HE a1;b1;14;d;e HA;HB;HC;HD;HE a2;b2;28;d;e HA;HB;HC;HD;HE a31;b31;44;d;e a32;b32;07;d;e HA;HB;HC;HD;HE a4;b4;0;d;e HA;HB;HC;HD;HE a51;b51;32;d;e a52;b52;0;d;e a53;b
HA;血红蛋白;HC;高清;他
。以下文件记录了6个条目(由上面的标题分隔)
我想提取每个条目的第三个属性(HC
)
HA;HB;HC;HD;HE
a1;b1;14;d;e
HA;HB;HC;HD;HE
a2;b2;28;d;e
HA;HB;HC;HD;HE
a31;b31;44;d;e
a32;b32;07;d;e
HA;HB;HC;HD;HE
a4;b4;0;d;e
HA;HB;HC;HD;HE
a51;b51;32;d;e
a52;b52;0;d;e
a53;b53;5;d;e
HA;HB;HC;HD;HE
a6;b6;10;d;e
每当每个条目记录了n
行HC
时,我想提取添加的n
条目
上述文件的预期输出:
14
28
51
0
37
10
14
28
51
0
37
10
我知道我可以为此编写一个程序,但是有没有一种简单的方法可以通过组合使用
awk
和/或sed
命令来实现呢?我还没有测试过这个;试试看,让我知道它是否有效
awk -F';' '
$3 == "HC" {
if (NR > 1) {
print sum
sum = 0 }
next }
{ sum += $3 }
END { print sum }'
我还没有测试过这个;试试看,让我知道它是否有效
awk -F';' '
$3 == "HC" {
if (NR > 1) {
print sum
sum = 0 }
next }
{ sum += $3 }
END { print sum }'
对于给定的输入:
$ cat infile
HA;HB;HC;HD;HE
a1;b1;14;d;e
HA;HB;HC;HD;HE
a2;b2;28;d;e
HA;HB;HC;HD;HE
a31;b31;44;d;e
a32;b32;07;d;e
HA;HB;HC;HD;HE
a4;b4;0;d;e
HA;HB;HC;HD;HE
a51;b51;32;d;e
a52;b52;0;d;e
a53;b53;5;d;e
HA;HB;HC;HD;HE
a6;b6;10;d;e
$ awk -F';' '/^H.*/{if(f)print s; s=0; f=$3=="HC"}f{s+=$3}END{if(f)print s}' infile
14
28
51
0
37
10
它不需要更多的注意,例如:
$ cat infile2
HA;HB;HC;HD;HE
a1;b1;14;d;e
HA;HB;HC;HD;HE
a2;b2;28;d;e
HA;HB;HC;HD;HE
a31;b31;44;d;e
a32;b32;07;d;e
HA;HB;HC;HD;HE
a4;b4;0;d;e
HA;HB;HD;HD;HE <---- Say if HC does not found
a51;b51;32;d;e
a52;b52;0;d;e
a53;b53;5;d;e
HA;HB;HC;HD;HE
a6;b6;10;d;e
# find only HC in 3rd column
$ awk -F';' '/^H.*/{if(f)print s; s=0; f=$3=="HC"}f{s+=$3}END{if(f)print s}' infile2
14
28
51
0
10
# Find HD in 3rd column
$ awk -F';' '/^H.*/{if(f)print s; s=0; f=$3=="HD"}f{s+=$3}END{if(f)print s}' infile2
37
$cat infile2
哈血红蛋白;HC;高清;他
a1;b1;14;DE
哈血红蛋白;HC;高清;他
a2;b2;28;DE
哈血红蛋白;HC;高清;他
a31;b31;44;DE
a32;b32;07;DE
哈血红蛋白;HC;高清;他
a4;b4;0;DE
哈血红蛋白;高清;高清;他
对于给定的输入:
$ cat infile
HA;HB;HC;HD;HE
a1;b1;14;d;e
HA;HB;HC;HD;HE
a2;b2;28;d;e
HA;HB;HC;HD;HE
a31;b31;44;d;e
a32;b32;07;d;e
HA;HB;HC;HD;HE
a4;b4;0;d;e
HA;HB;HC;HD;HE
a51;b51;32;d;e
a52;b52;0;d;e
a53;b53;5;d;e
HA;HB;HC;HD;HE
a6;b6;10;d;e
$ awk -F';' '/^H.*/{if(f)print s; s=0; f=$3=="HC"}f{s+=$3}END{if(f)print s}' infile
14
28
51
0
37
10
它不需要更多的注意,例如:
$ cat infile2
HA;HB;HC;HD;HE
a1;b1;14;d;e
HA;HB;HC;HD;HE
a2;b2;28;d;e
HA;HB;HC;HD;HE
a31;b31;44;d;e
a32;b32;07;d;e
HA;HB;HC;HD;HE
a4;b4;0;d;e
HA;HB;HD;HD;HE <---- Say if HC does not found
a51;b51;32;d;e
a52;b52;0;d;e
a53;b53;5;d;e
HA;HB;HC;HD;HE
a6;b6;10;d;e
# find only HC in 3rd column
$ awk -F';' '/^H.*/{if(f)print s; s=0; f=$3=="HC"}f{s+=$3}END{if(f)print s}' infile2
14
28
51
0
10
# Find HD in 3rd column
$ awk -F';' '/^H.*/{if(f)print s; s=0; f=$3=="HD"}f{s+=$3}END{if(f)print s}' infile2
37
$cat infile2
哈血红蛋白;HC;高清;他
a1;b1;14;DE
哈血红蛋白;HC;高清;他
a2;b2;28;DE
哈血红蛋白;HC;高清;他
a31;b31;44;DE
a32;b32;07;DE
哈血红蛋白;HC;高清;他
a4;b4;0;DE
哈血红蛋白;高清;高清;他
说明:
使用cat
使用的分隔符只取第三列代码>
将HC
行替换为0;expr 0
值开始构建eval
-bash表达式,最终生成expr 0+14代码>
用@
临时替换\n
换行符,以规避可能的BSDsed
限制
将双@
替换为单@
,以避免空行变成空格并导致expr
爆炸
用+
替换@
,将数字相加
执行命令,但使用true | | 0;expr…
以避免第一行出现保证语法错误
这就产生了:
true || 0; expr 0 + 14 + 0; expr 0 + 28 + 0; expr 0 + 44 + 07 + 0; expr 0 + 0 + 0; expr 0 + 32 + 0 + 5 + 0; expr 0 + 10
输出如下所示:
14
28
51
0
37
10
这在Bash3.2和MacosElCapitan上进行了测试
说明:
使用cat
使用的分隔符只取第三列代码>
将HC
行替换为0;expr 0
值开始构建eval
-bash表达式,最终生成expr 0+14代码>
用@
临时替换\n
换行符,以规避可能的BSDsed
限制
将双@
替换为单@
,以避免空行变成空格并导致expr
爆炸
用+
替换@
,将数字相加
执行命令,但使用true | | 0;expr…
以避免第一行出现保证语法错误
这就产生了:
true || 0; expr 0 + 14 + 0; expr 0 + 28 + 0; expr 0 + 44 + 07 + 0; expr 0 + 0 + 0; expr 0 + 32 + 0 + 5 + 0; expr 0 + 10
输出如下所示:
14
28
51
0
37
10
这在Bash 3.2和MacOS El Capitan上进行了测试。awk解决方案:
$ awk -F';' '$3=="HC" && p{
print sum # print current total
sum=p=0 # reinitialize sum and p
next
}
$3!="HC"{
sum=sum+($3+0) # make sure $3 is converted to integer. sum it up.
p=1 # set p to 1
} # print last sum
END{print sum}' input.txt
输出:
14
28
51
0
37
10
一艘班轮:
$ awk -F";" '$3=="HC" && p{print sum;sum=p=0;next} $3!="HC"{sum=sum+($3+0);p=1} END{print sum}' input.txt
awk解决方案:
$ awk -F';' '$3=="HC" && p{
print sum # print current total
sum=p=0 # reinitialize sum and p
next
}
$3!="HC"{
sum=sum+($3+0) # make sure $3 is converted to integer. sum it up.
p=1 # set p to 1
} # print last sum
END{print sum}' input.txt
输出:
14
28
51
0
37
10
一艘班轮:
$ awk -F";" '$3=="HC" && p{print sum;sum=p=0;next} $3!="HC"{sum=sum+($3+0);p=1} END{print sum}' input.txt
请您尝试以下内容,并让我知道这是否有助于您
awk -F";" '
/^H/ && $3!="HC"{
flag="";
next
}
/^H/ && $3=="HC"{
if(NR>1){
printf("%d\n",sum)
};
sum=0;
flag=1;
next
}
flag{
sum+=$3
}
END{
printf("%d\n",sum)
}
' Input_file
输出如下
请您尝试以下内容,并让我知道这是否有助于您
awk -F";" '
/^H/ && $3!="HC"{
flag="";
next
}
/^H/ && $3=="HC"{
if(NR>1){
printf("%d\n",sum)
};
sum=0;
flag=1;
next
}
flag{
sum+=$3
}
END{
printf("%d\n",sum)
}
' Input_file
输出如下
这将返回7个零。。但是让我来玩玩这个想法,看看我是否能让它发挥作用。它返回7个零。。但让我来玩玩这个想法,看看我是否能让它发挥作用。