通过使用AWK匹配、重命名和赋值来提取列
我有一个以制表符分隔的csv文件,其中包含对象长度的摘要统计信息:通过使用AWK匹配、重命名和赋值来提取列,awk,aggregate,Awk,Aggregate,我有一个以制表符分隔的csv文件,其中包含对象长度的摘要统计信息: sampled. objs. obj. min. len. obj. mean. len. obj. max. len. obj. std. 50 22 60 95 5 我希望通过搜索匹配的列标题obj来获得关于最小和最大长度的信息。莱恩小姐。和obj。马克斯·莱恩。。然后我想创建一个新的csv文件,用逗号分隔,并用新的列标题来获得结果 object_minimum,object_maximum 22,95 我
sampled. objs. obj. min. len. obj. mean. len. obj. max. len. obj. std.
50 22 60 95 5
我希望通过搜索匹配的列标题obj来获得关于最小和最大长度的信息。莱恩小姐。和obj。马克斯·莱恩。。然后我想创建一个新的csv文件,用逗号分隔,并用新的列标题来获得结果
object_minimum,object_maximum
22,95
我首先打印新的标题。然后我尝试检索匹配的索引,然后使用这些索引从第二行提取:
#!/bin/awk -f
BEGIN {
cols="object_minimum:object_maximum"
FS="\t"
RS="\n"
col_count=split(cols, col_arr, ":");
for(i=1; i<=col_count; i++) printf col_arr[i] ((i==col_count) ? "\n" : ",");
}
{
for (i=1; i<=NF; i++) {
if(index($i,"obj. min. len.") !=0) {
data["object_minimum"]=i;
}
if(index($i,"obj. max. len.") !=0) {
data["object_maximum"]=i;
}
}
}
END NR==1 {
for (j=1; j<=col_count; j++) printf NF==data[j] ((i==col_count) ? "\n" : ",");
}
请您尝试以下内容,完全基于您展示的样本,用GNU awk编写和测试。创建了一个名为sep=的awk变量,也可以根据需要进行更改
awk -v sep="###" '
BEGIN{
OFS=","
}
FNR==1{
while(match($0,/ +obj\./)){
val=substr($0,RSTART,RLENGTH)
sub(/^ +/,"",val)
line=(line?line:"")substr($0,1,RSTART-1)sep val
$0=substr($0,RSTART+RLENGTH)
}
if(substr($0,RSTART+RLENGTH)!=""){
line=line substr($0,RSTART+RLENGTH)
}
num=split(line,arr,sep)
for(i=1;i<=num;i++){
if(arr[i]=="obj. min. len."){ min=i }
if(arr[i]=="obj. max. len."){ max=i }
}
print "object_minimum,object_maximum"
next
}
{
print $min,$max
}
' Input_file
逻辑解释:处理输入文件的第一行。然后使用awk的match函数查找匹配项+obj\。在当前行中。在本例中,创建一个具有匹配值和匹配前值的变量。完成对特定正则表达式的所有搜索后,即会找到所有匹配正则表达式。然后用分隔符拆分新创建的变量,假设它们不存在于您的输入文件中,则使用分隔符将它们转换为数组中的其他值。最后检查该数组的所有元素,并在列为obj时设置条件。莱恩小姐。然后将最小变量值设置为特定的索引号,该索引号实际上是其余行的字段号,若值为obj。马克斯·莱恩。然后设置max变量。在处理完第一行后,只需通过$min、$max.打印相应的字段。您是否可以尝试以下内容,完全基于所显示的样本,使用GNU awk编写和测试。创建了一个名为sep=的awk变量,也可以根据需要进行更改
awk -v sep="###" '
BEGIN{
OFS=","
}
FNR==1{
while(match($0,/ +obj\./)){
val=substr($0,RSTART,RLENGTH)
sub(/^ +/,"",val)
line=(line?line:"")substr($0,1,RSTART-1)sep val
$0=substr($0,RSTART+RLENGTH)
}
if(substr($0,RSTART+RLENGTH)!=""){
line=line substr($0,RSTART+RLENGTH)
}
num=split(line,arr,sep)
for(i=1;i<=num;i++){
if(arr[i]=="obj. min. len."){ min=i }
if(arr[i]=="obj. max. len."){ max=i }
}
print "object_minimum,object_maximum"
next
}
{
print $min,$max
}
' Input_file
逻辑解释:处理输入文件的第一行。然后使用awk的match函数查找匹配项+obj\。在当前行中。在本例中,创建一个具有匹配值和匹配前值的变量。完成对特定正则表达式的所有搜索后,即会找到所有匹配正则表达式。然后用分隔符拆分新创建的变量,假设它们不存在于您的输入文件中,则使用分隔符将它们转换为数组中的其他值。最后检查该数组的所有元素,并在列为obj时设置条件。莱恩小姐。然后将最小变量值设置为特定的索引号,该索引号实际上是其余行的字段号,若值为obj。马克斯·莱恩。然后设置max变量。在处理完第一行后,只需通过执行$min、$max.打印相应的字段。这里是一个工作原型,添加格式和错误检查
$ awk -F'\t' -v OFS=, '
NR==1 {for(i=1;i<=NF;i++)
if($i=="obj. min. len.") min=i;
else if($i=="obj. max. len.") max=i;
print "min","max"}
NR==2 {print $min,$max; exit}' file
min,max
22,95
这里是一个工作原型,添加格式和错误检查
$ awk -F'\t' -v OFS=, '
NR==1 {for(i=1;i<=NF;i++)
if($i=="obj. min. len.") min=i;
else if($i=="obj. max. len.") max=i;
print "min","max"}
NR==2 {print $min,$max; exit}' file
min,max
22,95
使用awk:
输出:
22,95
资料来源:
请参阅:带awk:
输出:
22,95
资料来源:
请参阅:标题行中的列名是如何相互分隔的?看起来好像名字之间有两个空格,名字中有一个空格?那太恶心了。数据行中的列是否也用双空格分隔?您正在使用哪个版本的awk?您计划如何识别必须提取的输入列名和必须生成的输出列名,以及计划如何指定输出列的显示顺序?隐马尔可夫模型;您显示的awk脚本表明字段分隔符是选项卡-这更容易。请确认。设置OFS=,可能会节省一些焦虑-输出字段分隔符。同样,它可能没有任何好处,因为您可能需要在一行的多个printf调用中写出位和段。它是以制表符分隔的,标题名中有空格,我同意这不好,这就是为什么它们需要更改的原因。列的顺序和新列的名称由我如何指定cols给出。我首先以我想要的逗号分隔格式打印列名。然后我需要提取并打印下面的值,标题行中的列名是如何相互分离的?看起来好像名字之间有两个空格,名字中有一个空格?那太恶心了。数据行中的列是否也用双空格分隔?您正在使用哪个版本的awk?您计划如何识别必须提取的输入列名和必须生成的输出列名,以及计划如何指定输出列的显示顺序?隐马尔可夫模型;您显示的awk脚本表明字段分隔符是选项卡-这更容易。请确认。设置OFS=,可能会节省一些焦虑-输出字段分隔符。同样,它可能没有任何好处,因为您可能需要在一行的多个printf调用中写出位和段。它是以制表符分隔的,标题名中有空格,我同意这不好,这就是为什么它们需要更改的原因。列和na的顺序
新列的mes由我如何指定COL给出。我首先以我想要的逗号分隔格式打印列名。然后我需要提取并打印下面的值,显示的代码的哪个方面需要GNU Awk,而不是任何其他变量?它实际上并不打印映射的标题,但在其他方面却非常优雅。@JonathanLeffler:我通常只使用GNU awk进行测试。很公平-我不认为其中有任何代码依赖于awk的GNU特性。这是一个非常好、优雅的解决方案。@JonathanLeffler:谢谢你的提示。我已经更新了我的答案。所示代码的哪个方面需要GNU Awk,而不是任何其他变体?它实际上并不打印映射的标题,但在其他方面却非常优雅。@JonathanLeffler:我通常只使用GNU awk进行测试。很公平-我不认为其中有任何代码依赖于awk的GNU特性。这是一个非常好、优雅的解决方案。@JonathanLeffler:谢谢你的提示。我已经更新了我的答案。