繁体   English   中英

awk:select 匹配词后的第一列和列中的值

[英]awk: select first column and value in column after matching word

我有一个.csv,其中每一行对应一个人(第一列)和具有该人可用值的属性。 我想为属性可用的人提取特定属性的名称和值。 该文档的结构如下:

name,attribute1,value1,attribute2,value2,attribute3,value3
joe,height,5.2,weight,178,hair,
james,,,,,,
jesse,weight,165,height,5.3,hair,brown
jerome,hair,black,breakfast,donuts,height,6.8

我想要一个看起来像这样的文件:

name,attribute,value
joe,height,5.2
jesse,height,5.3
jerome,height,6.8

使用这篇较早的帖子,我尝试了几种不同的awk方法,但仍然无法同时获取第一列和任何具有所需属性值(比如高度)的列。 例如,以下返回所有内容。

awk -F "height," '{print $1 "," FS$2}' file.csv

我可以grep只有其中包含高度的行,但如果可以的话,我更愿意在一行中完成所有操作。

您可以使用此awk

cat attrib.awk

BEGIN {
   FS=OFS=","
   print "name,attribute,value"
}
NR > 1 && match($0, k "[^,]+") {
   print $1, substr($0, RSTART+1, RLENGTH-1)
}

# then run it as
awk -v k=',height,' -f attrib.awk file

name,attribute,value
joe,height,5.2
jesse,height,5.3
jerome,height,6.8

# or this one
awk -v k=',weight,' -f attrib.awk file

name,attribute,value
joe,weight,178
jesse,weight,165

使用您显示的示例,请尝试使用以下awk代码。 在 GNU awk中编写和测试。 简单的解释是,使用 GNU awk并将RS (记录分隔符)设置为^[^,]*,height,[^,]*然后根据要求打印 RT 以获得预期的 output。

awk -v RS='^[^,]*,height,[^,]*' 'RT{print RT}' Input_file

一个awk想法:

awk -v attr="height" '
BEGIN  { FS=OFS="," }
FNR==1 { print "name", "attribute", "value"; next }
       { for (i=2;i<=NF;i+=2)                         # loop through even-numbered fields
             if ($i == attr) {                        # if field value is an exact match to the "attr" variable then ...
                print $1,$i,$(i+1)                    # print current name, current field and next field to stdout
                next                                  # no need to check rest of current line; skip to next input line
             }
       }
' file.csv

注意:这假设输入值(本例中的height )将与文件中的字段完全匹配(包括相同的大小写)

这会产生:

name,attribute,value
joe,height,5.2
jesse,height,5.3
jerome,height,6.8

我建议使用sed

sed -n 's/^\([^,]*\).*\(,height,[^,]*\).*/\1\2/p' file.csv

使用

$ perl -lne '
    print "name,attribute,value" if $.==1;
    print "$1,$2" if /^(\w+).*(height,\d+\.\d+)/
' file

output

name,attribute,value
joe,height,5.2
jesse,height,5.3
jerome,height,6.8

awk在脚本之前的-v标志之后接受变量值 arguments。 因此,可以使用通用模式将所需属性的名称传递到 awk 脚本中:

awk -v attr=attribute1 ' {} ' file.csv

在脚本内部,传递的变量的值由变量名引用,在本例中为attr

您的标准是打印第 1 列,第一列包含名称,对应于所需 header 值的列,以及紧接在该列之后的列(包含匹配值)。

因此,以下脚本允许您找出标题为“attribute1”的列及其下一个邻居:

awk -v attr=attribute1 ' BEGIN {FS=","} /attr/{for (i=1;i<=NF;i++) if($i == attr) col=i;} {print $1","$col","$(col+1)} ' data.txt

结果:

name,attribute1,value1
joe,height,5.2
james,,
jesse,weight,165
jerome,hair,black

另一列(属性 3):

awk -v attr=attribute3 ' BEGIN {FS=","} /attr/{for (i=1;i<=NF;i++) if($i == attr) col=i;} {print $1","$col","$(col+1)} ' awkNames.txt

结果:

name,attribute3,value3
joe,hair,
james,,
jesse,hair,brown
jerome,height,6.8

只需更改所需列的-v attr=参数的值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM