我正在编写一个bash脚本来解析一堆(十几个或更多(巨大的Terraform文件,这些文件包含大量的google_bigquery_dataset资源及其关联的IAM访问块。脚本应该获取每个数据集资源,并将其复制到另一个以数据集本身命名的文件中。
所有这些都很好,除了从资源的";dataset_id";领域如果不是因为这些数据集资源中的一些已经授权的视图块也包含";dataset_id";价值观
下面是这样一个资源的例子:
resource "google_bigquery_dataset" "project-bigquery-dataset-RESOURCE_NAME" {
access {
role = "WRITER"
special_group = "projectWriters"
}
access {
role = "READER"
special_group = "projectReaders"
}
access {
role = "WRITER"
user_by_email = "user1@project.iam.gserviceaccount.com"
}
access {
role = "OWNER"
special_group = "projectOwners"
}
access {
view {
dataset_id = "DO_NOT_WANT"
project_id = "project"
table_id = "table1"
}
}
access {
view {
dataset_id = "DO_NOT_WANT"
project_id = "project"
table_id = "table2"
}
}
access {
view {
dataset_id = "DO_NOT_WANT"
project_id = "project"
table_id = "table3"
}
}
dataset_id = "THIS_IS_WHAT_I_WANT"
default_partition_expiration_ms = "0"
delete_contents_on_destroy = "false"
labels = {
application-name = "app-name"
}
location = "US"
project = "project"
}
在我意识到授权的视图块也有一个dataset_id
字段之前,我正在使用它来尝试获取我想要的值,假设startIndex
和endIndex
只是表示完整数据集资源块的开始和结束行号,如上所述:
fileName=$( sed -n ${startIndex},${endIndex}p $bigFile | grep "dataset_id" | cut -d" -f2)
只有在没有包含其他dataset_id
值的"授权视图"块的情况下才有效。
然后我试着使用负向后看:
fileName=$( sed -n ${startIndex},${endIndex}p $bigFile | grep '(?<!view {]n)dataset_id' | cut -f1 -d"
这行不通。我不确定是因为换行还是因为view {
结尾和dataset_id = "DO_NOT_WANT"
开头之间的空白。
我尝试过它的变体,比如(?<!views{s)s*dataset_id
,但没有成功。
有没有办法只捕获不在视图块中的dataset_id
?
注意事项:
- 我可以保证
view {
总是在块中的dataset_id
之前,没有换行 - 我不能保证订单。我试图捕捉的
dataset_id
可能出现在view
块之前、之后,甚至介于它们之间 - 上述示例的期望输出将简单地为
THIS_IS_WHAT_I_WANT
如有任何帮助,我们将不胜感激
只显示示例,请尝试以下awk
代码。用GNUawk
编写和测试。
awk -v RS= -v FS="n" '
/^[[:space:]]+dataset_id[[:space:]]+/{
split($1,arr,""")
print arr[2]
}
' Input_file
解释:完整代码的简单解释是:
- 在
awk
程序中将RS
(记录分隔符(设置为段落模式 - 然后将
FS
(字段分隔符(设置为新行 - 然后在主块检查条件下,如果行从1个或多个空格开始,然后是
dataset_id
,然后是1个或更多空格,如果此条件为TRUE,则: - 使用
awk
的split
函数将$1(第一个字段(拆分为一个名为arr
的数组,分隔符为"
。这基本上创建了一个名为arr
的数组,其索引为1 2 3 4,依此类推,具体取决于它根据分隔符拆分的元素数量 - 然后打印阵列
arr
的第二个元素,这是OP需要输出的
如果您的grep
支持-P
(PCRE(选项,请尝试以下操作。它是用你展示的样品测试的。
grep -Poz '(?:^|n)(?:(?!view).)*ns*dataset_ids*=s*"K[^"]+' input_file
输出:
THIS_IS_WHAT_I_WANT
假设
- 如果
view {
先于dataset_id
,则两个单词的跨度连续两行
解释
- 由于我们需要检查跨行的模式匹配,因此放置了
-z
选项到CCD_ 31以将输入视为行序列 - 正则表达式
(?:^|n)(?:(?!view).)*ns*dataset_ids*=s*"K[^"]+
匹配(至少(不包含单词view
的两行在包含CCD_ 34的行之前的前一行中 (?:^|n)
将线的起点固定为多行选项由于-z
选项,(?m)
不起作用- 由于
lookbehind
断言不允许可变长度匹配,我们需要使用CCD_ 39作为CCD_ - 以下
ns*dataset_id
确保至少有一个换行符存在于CCD_ 42和CCD_。否则,正则表达式与仅包含CCD_ 44的单线引起过检测 K
丢弃先前匹配的子串以将其排除在输出中
不能保证使用hcl,但可以尝试先转换为json
$ cat foo.tf |
yj -c |
jq -r '.resource[].google_bigquery_dataset[][][].dataset_id'
THIS_IS_WHAT_I_WANT
THIS_IS_WHAT_I_WANT