在匹配后的第一个空行之前提取行

时间:2017-09-08 10:12:38

标签: regex bash terminal text-processing

我有一些这种形式的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以获得相同的数字。

3 个答案:

答案 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数组的最后一个元素。