如何用Bash正则反向匹配提取Terraform文件中非view块的dataset_id
解决Terraform中提取google_bigquery_dataset顶层dataset_id的问题
问题分析
你需要从Terraform的google_bigquery_dataset资源块中提取顶层的dataset_id,但资源内的access.view块中也包含同名字段,导致普通文本匹配方法失效。核心需求是仅捕获不在view块内的dataset_id。
解决方案:用AWK跟踪块状态提取
由于view块和内部的dataset_id是跨行结构,逐行匹配的grep无法有效区分上下文,推荐用AWK跟踪当前是否处于view块内,精准提取目标字段:
fileName=$(sed -n "${startIndex},${endIndex}p" "$bigFile" | awk ' # 进入view块时标记状态 /view {/ { in_view = 1 } # 退出view块时取消标记(仅当当前在view块内时) /}/ { if (in_view) in_view = 0 } # 匹配不在view块内的dataset_id行,提取引号内的值 /dataset_id/ && !in_view { # 移除行首到dataset_id引号前的所有内容 sub(/.*dataset_id[[:space:]]*=[[:space:]]*"/, "", $0) # 移除引号及后面的所有内容 sub(/".*/, "", $0) print $0 exit # 每个资源仅一个顶层dataset_id,找到后直接退出 } ')
脚本逻辑说明
- 状态跟踪:通过
in_view变量标记当前是否处于view块内部,遇到view {时开启标记,遇到}且处于view块内时关闭标记。 - 精准匹配:仅处理包含
dataset_id且不在view块内的行。 - 值提取:通过两次
sub操作剥离字段名和引号,直接提取目标字符串。 - 效率优化:找到目标值后立即
exit,避免多余处理。
替代方案(仅当系统支持grep -P时)
如果你的系统grep支持Perl兼容正则(如Linux的GNU grep),可以用跨行匹配的思路,但可靠性不如AWK(依赖固定格式):
fileName=$(sed -n "${startIndex},${endIndex}p" "$bigFile" | grep -A1 -B100 "dataset_id" | grep -v "view {" | grep -oP '(?<=")[^"]+')
不过此方法依赖dataset_id周围的行结构,稳定性较差,优先推荐AWK方案。
内容的提问来源于stack exchange,提问作者dxh3707
相关产品推荐
相关产品推荐

