匹配后提取第一个空行之前的行
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>
我有一些这种形式的 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>