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

Extract line before first empty line after match

我有一些这种形式的 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 后使用相同的脚本提取相同类型的行,在上面的示例中将 return

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 以获得相同的数字。

awk表达式:

awk -v vec="KS vector" '[=10=]~vec{ f=1 }f && !NF{ print r; exit }f{ r=[=10=] }' file
  • vec - 包含所需 pattern/vector

  • 的变量
  • [=14=]~vec{ f=1 } - 遇到需要的 pattern/vector - 将标志 f 设置为活动状态

  • f{ r=[=16=] } - 当标志 f 处于活动状态时(在需要的向量部分下) - 将当前行捕获到变量 r

  • f && !NF{ print r; exit } - (NF - 字段总数,如果该行为空 - 没有字段 !NF) 在遍历时遇到空行所需的矢量线 - 打印最后捕获的非空行 r

  • exit - 立即退出脚本执行(避免冗余actions/iterations)

输出:

2; 1; d; 236.27

如果您只想打印找到的矢量下的实际行数,请使用以下命令:

awk -v vec="KS vector" '[=12=]~vec{ f=1 }f && !NF{ print r+1; exit }f{ r= }' file
3

使用 awk:

awk '[=10=] ~ "KS vector" { valid=1;getline } valid==1 { cnt++;dat[cnt]=[=10=] } [=10=]=="" { valid="" } END { print dat[cnt-1]  }' filename

检查是否有匹配 "KS vector" 的行。设置一个有效标志,然后读入下一行。将数据读入一个带有递增计数器的数组。当遇到space时,重新设置有效标志。最后打印 dat 数组的最后一个元素。

你的做法是错误的。您只需要将 awk 置于段落模式并打印比记录中的行数少 1(因为您不想在计数中包含 KS 向量行):

$ awk -v RS= -F'\n' '/KS vector/{print NF-1}' file
3

以下是当您将记录置于段落模式(通过将 RS 设置为 null)并使用换行符分隔的字段(通过将 FS 设置为换行符)时 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>