我有一些这种形式的CSV文件:
* COMMENT
* COMMENT
100 ; 1706 ; 0.18 ; 0.45 ; 0.00015 ; 0.1485 ; 0.03 ; 1 ; 1 ; 2 ; 280 ; 100 ; 100 ;
* COMMENT
* COMMENT
* ZT vector
0; 367; p; nan
1; 422; p; nan
2; 1; d; nan
* KS vector
0; 367; p; 236.27
1; 422; p; 236.27
2; 1; d; 236.27
*Total time: 4.04211
我需要在匹配模式KS vector
之后提取空行之前的最后一行。
为了更清楚,在上面的例子中我想提取行
2; 1; d; 236.27
因为在我与KS vector
匹配后,它在第一个空行之前是非空行。
我还想在匹配模式ZT vector
之后使用相同的脚本来提取相同类型的行,在上面的示例中将返回
2; 1; d; nan
我需要这样做,因为我需要该行的第一个数字,因为它告诉我KS vector
之后的连续非空行数。
我目前的解决方法是:
# counting number of lines after matching "KS vector" until first empty line
var=$(sed -n '/KS vector/,/^$/p' file | wc -l)
# Subtracting 2 to obtain actual number of lines
var=$(($var-2))
但是,如果我可以直接提取最后一行,我可以提取第一个元素(示例中为2
)并为其添加1以获得相同的数字。
答案 0 :(得分:3)
你这是错误的方式。您所需要的只是将awk置于段落模式并打印1小于记录中的行数(因为您不希望在计数中包含KS向量行):
$ awk -v RS= -F'\n' '/KS vector/{print NF-1}' file
3
以下是当你用新行分隔的字段(通过将FS设置为换行符)将awk置于段落模式(通过将RS设置为null)时,awk如何看到记录:
$ awk -v RS= -F'\n' '/KS vector/{ for (i=1;i<=NF;i++) print NF, i, "<"$i">"}' file
4 1 <* KS vector>
4 2 <0; 367; p; 236.27>
4 3 <1; 422; p; 236.27>
4 4 <2; 1; d; 236.27>
答案 1 :(得分:2)
使用 awk 表达式:
awk -v vec="KS vector" '$0~vec{ f=1 }f && !NF{ print r; exit }f{ r=$0 }' file
vec
- 包含所需模式/向量的变量
$0~vec{ f=1 }
- 遇到所需的模式/向量 - 将标志f
设置为活动状态
f{ r=$0 }
- 当标记f
处于活动状态时(在需要的向量部分下) - 将当前行捕获为变量r
f && !NF{ print r; exit }
- (NF
- 字段总数,如果该行为空 - 在遇到空行时没有字段!NF
),同时迭代所需的向量行 - 打印最后捕获的非空行r
exit
- 立即退出脚本执行(避免冗余操作/迭代)
输出:
2; 1; d; 236.27
如果您只想在找到的矢量下打印实际行数,请使用以下命令:
awk -v vec="KS vector" '$0~vec{ f=1 }f && !NF{ print r+1; exit }f{ r=$1 }' file
3
答案 2 :(得分:0)
使用awk:
awk '$0 ~ "KS vector" { valid=1;getline } valid==1 { cnt++;dat[cnt]=$0 } $0=="" { valid="" } END { print dat[cnt-1] }' filename
检查是否有匹配&#34; KS矢量&#34;的任何行。设置有效标志,然后读入下一行。使用递增的计数器将数据读入数组。遇到空间时,重置有效标志。最后打印dat数组的最后一个元素。