awk if else实现文件无匹配字符串时仅输出一次不存在提示
awk处理空行分隔块的匹配逻辑实现
场景说明
处理以空行分隔的多行块文本,实际使用场景输入源为lspci -v命令输出,以下方案通过模拟测试数据验证可直接复用。
测试输入为多组以空行分隔的name、data字段块,需求规则如下:
- 先将每个空行分隔的多行块合并为单行记录
- 对每条记录匹配目标字符串
var:- 若记录内
var后匹配到.*good,输出var is good - 若记录内存在
var但不符合上述规则,输出var is missing
- 若记录内
- 若整个文件完全不存在目标字符串
var,仅输出1次NON-EXISTING_DATA_REQUESTED,不重复输出多余提示
初始踩坑
最初直接在逐行处理逻辑中加else分支输出不存在提示,会出现三类异常:
- 所有不包含
var的记录行都会输出不存在提示 - 部分记录包含
var、部分不包含时,无匹配的行会输出冗余提示 - 全文件无
var时,会逐行输出多条重复的不存在提示
正确实现代码
通过全局标记位记录匹配状态,将全文件无匹配的判断放到END块执行,避免逐行误判:
# 处理本地测试文件 awk -v RS='' -v target="var" ' { # 重排字段,将当前空行分隔的多行块合并为单行 $1 = $1 # 判断当前记录是否包含目标字符串 if (index($0, target) > 0) { found = 1 if (match($0, target ".*good")) { print target " is good" } else { print target " is missing" } } } END { # 所有记录处理完后,若从未匹配到目标则仅输出一次提示 if (!found) { print "NON-EXISTING_DATA_REQUESTED" } } ' xx
实际对接lspci -v输入时直接管道传入即可,无需生成中间文件:
lspci -v | awk -v RS='' -v target="var" ' { $1 = $1 if (index($0, target) > 0) { found = 1 print (match($0, target ".*good") ? target " is good" : target " is missing") } } END { if (!found) print "NON-EXISTING_DATA_REQUESTED" } '
逻辑说明
-v RS=''是awk内置的空行分隔记录模式,会自动将连续空行作为记录分隔符,刚好匹配空行分隔块的文本结构- 全局变量
found初始值为0,只要任意一条记录匹配到目标字符串就置为1,不匹配的记录直接跳过不输出任何内容 - 单条记录的匹配判断用
index做字符串精确查找,相比正则匹配效率更高,也能避免目标字符串含正则特殊字符导致的匹配异常;如果需要用正则匹配目标,可将index($0, target) > 0替换为$0 ~ target - 全文件无匹配的判断放在
END块执行,仅在所有记录遍历完成、found标记始终为0时输出1次提示,从根源避免重复输出问题
内容的提问来源于stack exchange,提问作者monk
相关产品推荐
相关产品推荐

