如何使用grep或awk从变量中提取All files对应数值
问题描述
现有存储测试覆盖率输出的变量$RES,内容为|分隔的表格格式,截断后的示例内容如下:
----- File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s ----------------------------------|---------|----------|---------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- All files | 36.95 | 20.87 | 24.
原始输出内容很长,发帖时已做截断处理,经测试All files字段位于内容的970-990字符位置。
当前通过固定字符位置截取的实现如下:
TOTAL="$(cut -c 975-990 <<< $RES)"
该方案依赖固定字符偏移,鲁棒性差,需要更通用可靠的正则匹配实现方案,已知grep、awk等工具可实现这类文本提取需求,但不清楚对应匹配规则的编写方法,目标是提取All files对应的第一个数值(即示例中的36.95)。
通用实现方案
以下方案均不依赖固定字符位置,只要输出保持「|作为列分隔符、All files后第一列为总语句覆盖率」的格式规则,即可稳定提取目标值。
awk 方案(适配表格场景最简便)
直接按|分割列,定位到包含All files的内容段后取对应列即可:
TOTAL="$(awk -F'|' '/All files/ {gsub(/[[:space:]]+/,"",$2); print $2; exit}' <<< "$RES")
- 参数逻辑说明:
-F'|':指定|为列分隔符/All files/:匹配到包含All files的内容段后执行大括号内的逻辑gsub(/[[:space:]]+/,"",$2):清除第二列(All files后第一个数值列)的所有空白字符print $2输出目标值后执行exit终止处理,避免匹配后续冗余内容- 引用
$RES时需加双引号,避免内容中的空格、换行被shell解析吞掉
grep 正则提取方案
使用GNU grep的PCRE正则模式,直接定位目标数值:
TOTAL="$(grep -oP 'All files\s*\|\s*\K[0-9.]+' <<< "$RES" | head -n1)"
- 参数逻辑说明:
-o:仅输出匹配到的内容片段,而非整行-P:启用Perl兼容正则语法,支持\K语法(匹配时忽略\K之前的所有内容,不将其计入输出结果)- 正则匹配逻辑:先匹配
All files字段,跳过其后任意数量的空白字符、分隔符|、分隔符后任意数量的空白字符,后续连续的数字和小数点即为目标覆盖率值 head -n1:确保仅取第一个匹配结果,避免冗余输出干扰
纯Bash内置方案(无外部命令依赖)
如果追求性能,不想调用awk、grep等外部进程,可直接使用Bash自带的正则匹配能力:
if [[ $RES =~ All\ files[[:space:]]*\|[[:space:]]*([0-9.]+) ]]; then TOTAL="${BASH_REMATCH[1]}" fi
- 逻辑说明:
=~是Bash原生支持的正则匹配操作符,匹配成功后,捕获组的内容会按顺序存入BASH_REMATCH数组,下标1对应第一个括号捕获组的内容,也就是目标数值- 该方案全程在Shell内部完成,无额外进程创建开销,执行效率最高
注意:以上方案均兼容输出长度变化、前后新增冗余内容的场景,比固定字符位截取的方案可靠性高很多。
内容的提问来源于stack exchange,提问作者leo
相关产品推荐
相关产品推荐

