我正在编写一个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"
开头之间的空格。
我尝试过它的变体,比如(?<!view\s{\s)\s*dataset_id
,但没有成功。
有没有办法只捕获不在视图块中的dataset_id
?
几个注意事项:
1.我可以保证view {
在块中始终位于dataset_id
之前,没有换行符。
1.我不能保证顺序,我尝试捕获的dataset_id
可能出现在view
块之前,之后,甚至在它们之间的某个地方。
1.上述示例的所需输出仅为THIS_IS_WHAT_I_WANT
。如有任何帮助,将不胜感激。
3条答案
按热度按时间vdgimpew1#
对于您展示的示例,请尝试以下
awk
代码。在GNUawk
中编写和测试。***说明:***完整代码的简单说明如下:
awk
程序中将RS
(记录分隔符)设置为段落模式。FS
(字段分隔符)设置为新行。dataset_id
,再然后是1个或多个空格,如果此条件为TRUE,则:awk
的split
函数将$1(第一个字段)拆分到一个名为arr
的数组中,分隔符为"
。这基本上创建了一个名为arr
的数组,索引为1 2 3 4,依此类推,具体取决于它根据分隔符拆分了多少个元素。arr
的第2个元素。68bkxrlz2#
如果您的
grep
支持-P
(PCRE)选项,请尝试以下操作。它已通过您所示的示例进行了测试。输出:
view {
先于dataset_id
,则这两个字跨越连续的两行。-z
选项被置于grep
,以将输入视为行序列。(?:^|\n)(?:(?!view).)*\n\s*dataset_id\s*=\s*"\K[^"]+
匹配(至少)包含dataset_id
的行之前的前一行中不包含单词view
的两行。(?:^|\n)
定位线的起点,因为多行选项(?m)
由于-z
选项而不起作用。lookbehind
Assert不允许可变长度匹配,我们需要使用(?:(?!view).)*
作为(?<!view.*)
的替代。\n\s*dataset_id
确保view
和dataset_id
之间至少存在一个换行符。否则,正则表达式匹配仅包含dataset_id
的单行,从而导致过度检测。\K
丢弃先前匹配的子字符串以将其排除在输出之外。628mspwn3#
我不能保证能和你的hcl一起工作,但是可以先尝试转换成json