我正在尝试从我的文件中提取特定字段。基本上,输出字段仅包含匹配的表达式,输出在匹配的记录之后开始。
这是我输入的一个例子。有时字段的顺序不同,并且在我尝试匹配的标题之前有不同的行数。
我很难找到如何使用cut和sed命令实现这一点,并且找不到awk方法。
CGATS.17
FORMAT_VERSION 1
KEYWORD "SampleID"
KEYWORD "SAMPLE_NAME"
NUMBER_OF_FIELDS 45
WEIGHTING_FUNCTION "ILLUMINANT, D50"
WEIGHTING_FUNCTION "OBSERVER, 2 degree"
BEGIN_DATA_FORMAT
SampleID SAMPLE_NAME CMYK_C CMYK_M CMYK_Y CMYK_K LAB_L LAB_A LAB_B nm380 nm390 nm400
END_DATA_FORMAT
NUMBER_OF_SETS 182
BEGIN_DATA
1 1 40 40 40 0 62.5 6.98 4.09 0.195213 0.205916 0.212827
2 2 0 40 40 0 73.69 25.48 24.89 0.200109 0.211081 0.218222
3 3 40 40 0 0 63.95 12.14 -20.91 0.346069 0.365042 0.377148
4 4 0 70 70 0 58.91 47.69 35.54 0.080033 0.084421 0.087317
END_DATA
这是我使用的脏代码,它主要完成了工作,但没有字段标题条件搜索。 awk命令只是删除输出周围的空行。
cut -f 7-9 -s input.txt |
sed -E 's/(LAB_.)//g' |
awk 'NF' > file.txt
我期望的输出看起来像这样。它仍然以制表符分隔,仅包含直接从(LAB _。)
开始的字段的值62.5 6.98 4.09
73.69 25.48 24.89
63.95 12.14 -20.91
58.91 47.69 35.54
答案 0 :(得分:1)
#!/usr/bin/awk -f
# We look for line starting with BEGIN_DATA_FORMAT do the getline function and
# store location of fields that have "LAB" in their name on the next line.
/^BEGIN_DATA_FORMAT/{
getline
for (i=1;i<=NF;i++)
if ($i~/LAB/) a[i]=$i
}
# In this regex range we look for lines that have more than 2 fields. For those
# lines we loop thru each field and see if the location matches to the ones
# captured in our earlier array (i.e location number of fields that have "LAB"
# in their name). If we find a match we print those fields.
/^BEGIN_DATA$/,/^END_DATA$/{
s="";
if (NF<2) next; else
for (j in a)
s=s?s"\t"$j:$j
print s;
}
[jaypal:~/Temp] ./script.awk file
62.5 6.98 4.09
73.69 25.48 24.89
63.95 12.14 -20.91
58.91 47.69 35.54
答案 1 :(得分:1)
另一个awk脚本:
awk '/^BEGIN_DATA_FORMAT/{getline;f=NF;for(i=1;i<=NF;i++)if($i~/^LAB_[LAB]/)l[i]++;}
/^BEGIN_DATA/,/^END_DATA/ && NF==f{s=""; for(x in l)s=s?s"\t"$x:$x; print s;}' input
示例输入的输出:
62.5 6.98 4.09
73.69 25.48 24.89
63.95 12.14 -20.91
58.91 47.69 35.54
上面的awk脚本的一些注释:
标题处理与@ JayPal的解决方案类似,但略有不同 不同:你提到列顺序可能不同,所以 对于标题匹配,我的awk脚本查找了下一行 “BEGIN_DATA_FORMAT”。因为头线的第一列可以 SampleID以外的东西。
,如您所料,仅打印值([tab]分隔), 但没有头。如果你说列的顺序可以变化,你 可能会丢失标题信息。比方说,哪一列是LAB_L哪个是A?等等 如果确实需要,这可以轻松完成。
答案 2 :(得分:0)
这可能对您有用:
sed '/^BEGIN_DATA\>/,/^END_DATA\>/{//d;s/\(\S*\s*\)\{6\}\(\S*\s*\S*\s*\S*\).*/\2/p};d' file
或者留在cut
:
cut -f7-9 file | sed '/^\([-.0-9]*\s*[-.0-9]*\s*[-.0-9.]*$\)/!d'
或者(但我猜这里输入文件的格式):
sed 's/\s*$//' file | cut -f7-9 | sed '/^BEGIN_DATA$/,/^END_DATA$/{//d;p};d'