[英]detect jinja2 variables that has if statement using regex - python
從下面的文件中,我只想提取 if 語句塊並對其進行迭代還想僅提取具有 image: as key 的塊
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: {{ template "fullname" . }}
labels:
app: {{ template "fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
spec:
replicas: {{ .Values.replicas }}
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
minReadySeconds: 5
template:
metadata:
labels:
name: {{ template "fullname" . }}
app: {{ template "fullname" . }}
spec:
{{- if .Values.pvc.enabled }}
volumes:
- name: {{ template "fullname" . }}
persistentVolumeClaim:
claimName: {{ template "claimname" . }}
{{- end }}
{{- if .Values.k8swait.enabled }}
serviceAccountName: {{ template "fullname" . }}-admin
initContainers:
- env:
- name: CLUSTER
value: "{{ .Values.k8swait.parameters.cluster}}"
- name: NAMESPACE
value: "{{ .Release.Namespace }}"
- name: RESOURCE
value: "{{ .Values.k8swait.parameters.resource}}"
- name: RNAME
value: "{{ .Values.k8swait.job.jobname }}"
- name: TIMEOUT
value: "{{ .Values.k8swait.parameters.timeout}}"
- name: FREQUENCE
value: "{{ .Values.k8swait.parameters.frequence}}"
name: {{ .Values.k8swait.parameters.name}}
image: "{{ .Values.global.registry1 }}/{{ .Values.k8swait.repo }}:{{ .Values.k8swait.tag }}"
resources:
limits:
cpu: "{{ .Values.resources.limits.cpu }}"
memory: "{{ .Values.resources.limits.memory }}"
requests:
cpu: "{{ .Values.resources.requests.cpu }}"
memory: "{{ .Values.resources.requests.memory }}"
{{- end }}
securityContext:
runAsUser: 1000
fsGroup: 1000
containers:
- name: {{ template "fullname" . }}
image: "{{ .Values.global.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ default "" .Values.imagePullPolicy | quote }}
ports:
- name: http
containerPort: 9000
{{- if .Values.pvc.enabled }}
image: "{{ .Values.global.registry1 }}/{{ .Values.k8swait.repo }}:{{ .Values.k8swait.tag }}"
volumeMounts:
- mountPath: /BACKUP
name: "{{ template "fullname" . }}"
{{- end }}
所需的 output:
{{- if .Values.k8swait.enabled }}
serviceAccountName: {{ template "fullname" . }}-admin
initContainers:
- env:
- name: CLUSTER
value: "{{ .Values.k8swait.parameters.cluster}}"
- name: NAMESPACE
value: "{{ .Release.Namespace }}"
- name: RESOURCE
value: "{{ .Values.k8swait.parameters.resource}}"
- name: RNAME
value: "{{ .Values.k8swait.job.jobname }}"
- name: TIMEOUT
value: "{{ .Values.k8swait.parameters.timeout}}"
- name: FREQUENCE
value: "{{ .Values.k8swait.parameters.frequence}}"
name: {{ .Values.k8swait.parameters.name}}
image: "{{ .Values.global.registry1 }}/{{ .Values.k8swait.repo }}:{{ .Values.k8swait.tag }}"
resources:
limits:
cpu: "{{ .Values.resources.limits.cpu }}"
memory: "{{ .Values.resources.limits.memory }}"
requests:
cpu: "{{ .Values.resources.requests.cpu }}"
memory: "{{ .Values.resources.requests.memory }}"
{{- end }}
{{- if .Values.pvc.enabled }}
image: "{{ .Values.global.registry1 }}/{{ .Values.k8swait.repo }}:{{ .Values.k8swait.tag }}"
volumeMounts:
- mountPath: /BACKUP
name: "{{ template "fullname" . }}"
{{- end }}
我已經嘗試了以下代碼,但它無法正常工作
with open(args.dataFileName) as fd:
data = fd.read()
match = re.findall(r'{{-?\s?if .+ end\s?}}', data, re.DOTALL)
如您所見,所需的 output 僅包含 if 語句塊,該語句塊將圖像作為鍵,在任何提示中如何使用正則表達式實現這一點?
正則表達式的一個限制是,這僅在if
塊沒有嵌套時才有效。
另外,我只熟悉用於 Jinja2 中的if 塊的{% if %}
和{% endif %}
。 因此,我正在跟隨您尋找{{-?\s*if\s*}}
和{{-?\s*end\s*}}
。 如果這不正確,很容易糾正。
import re
text = """apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: {{ template "fullname" . }}
labels:
app: {{ template "fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
spec:
replicas: {{ .Values.replicas }}
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
minReadySeconds: 5
template:
metadata:
labels:
name: {{ template "fullname" . }}
app: {{ template "fullname" . }}
spec:
{{- if .Values.pvc.enabled }}
volumes:
- name: {{ template "fullname" . }}
persistentVolumeClaim:
claimName: {{ template "claimname" . }}
{{- end }}
{{- if .Values.k8swait.enabled }}
serviceAccountName: {{ template "fullname" . }}-admin
initContainers:
- env:
- name: CLUSTER
value: "{{ .Values.k8swait.parameters.cluster}}"
- name: NAMESPACE
value: "{{ .Release.Namespace }}"
- name: RESOURCE
value: "{{ .Values.k8swait.parameters.resource}}"
- name: RNAME
value: "{{ .Values.k8swait.job.jobname }}"
- name: TIMEOUT
value: "{{ .Values.k8swait.parameters.timeout}}"
- name: FREQUENCE
value: "{{ .Values.k8swait.parameters.frequence}}"
name: {{ .Values.k8swait.parameters.name}}
image: "{{ .Values.global.registry1 }}/{{ .Values.k8swait.repo }}:{{ .Values.k8swait.tag }}"
resources:
limits:
cpu: "{{ .Values.resources.limits.cpu }}"
memory: "{{ .Values.resources.limits.memory }}"
requests:
cpu: "{{ .Values.resources.requests.cpu }}"
memory: "{{ .Values.resources.requests.memory }}"
{{- end }}
securityContext:
runAsUser: 1000
fsGroup: 1000
containers:
- name: {{ template "fullname" . }}
image: "{{ .Values.global.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ default "" .Values.imagePullPolicy | quote }}
ports:
- name: http
containerPort: 9000
{{- if .Values.pvc.enabled }}
image: "{{ .Values.global.registry1 }}/{{ .Values.k8swait.repo }}:{{ .Values.k8swait.tag }}"
volumeMounts:
- mountPath: /BACKUP
name: "{{ template "fullname" . }}"
{{- end }}"""
start_if = r'{{-?\s*if\s*[^}]+}}' # {{- if }}
end_if = r'{{-?\s*end\s*}}' # {{- end }}
regex = re.compile(f'{start_if}(.*?){end_if}', flags=re.DOTALL)
matches = [m.group(0) for m in regex.finditer(text) if 'image: ' in m.group(1)]
for match in matches:
print(match)
print()
印刷:
{{- if .Values.k8swait.enabled }}
serviceAccountName: {{ template "fullname" . }}-admin
initContainers:
- env:
- name: CLUSTER
value: "{{ .Values.k8swait.parameters.cluster}}"
- name: NAMESPACE
value: "{{ .Release.Namespace }}"
- name: RESOURCE
value: "{{ .Values.k8swait.parameters.resource}}"
- name: RNAME
value: "{{ .Values.k8swait.job.jobname }}"
- name: TIMEOUT
value: "{{ .Values.k8swait.parameters.timeout}}"
- name: FREQUENCE
value: "{{ .Values.k8swait.parameters.frequence}}"
name: {{ .Values.k8swait.parameters.name}}
image: "{{ .Values.global.registry1 }}/{{ .Values.k8swait.repo }}:{{ .Values.k8swait.tag }}"
resources:
limits:
cpu: "{{ .Values.resources.limits.cpu }}"
memory: "{{ .Values.resources.limits.memory }}"
requests:
cpu: "{{ .Values.resources.requests.cpu }}"
memory: "{{ .Values.resources.requests.memory }}"
{{- end }}
{{- if .Values.pvc.enabled }}
image: "{{ .Values.global.registry1 }}/{{ .Values.k8swait.repo }}:{{ .Values.k8swait.tag }}"
volumeMounts:
- mountPath: /BACKUP
name: "{{ template "fullname" . }}"
{{- end }}
即使您有嵌套的 if 語句,您仍然可以使用正則表達式執行此操作,並且解析文本文件會很快:
import re
code = """
some text ....some text ....some text ....
some text ....some text ....some text ....
{{- if .Values.pvc.enabled [don't extract this 0]}}
some text ....
{{- end }}
{{- if .Values.k8swait.enabled [extract this 1}}
some text ....
image:
{{- end }}
{{- if .Values.k8swait.enabled [extract this 2]}}
some text ....
image: 000
{{- if [extract this 3]}}
image: 000
{{- end }}
{{- end }}
{{- if .Values.k8swait.enabled [extract this 4}}
some text ....
image:
{{- end }}
{{- if .Values.k8swait.enabled [extract this 5]}}
some text ....
image: 000
{{- if [don't extract this sub if 6 ]}}
{{- end }}
{{- end }}
"""
def extract_image_if_statement(text):
# this to extract nested ifs or if preceded by if statements
sub_if = re.compile("((?:{{-\s*if.+?)+)({{-\s*if.+?end\s*}})", re.DOTALL)
# this to extract if statement that left by the first pattern
outer_if = re.compile("{{-\s*if.+?end\s*}}", re.DOTALL)
# used to get the if statement by index from expression list
get_if = re.compile("#(\d)#")
# used to build back full nested expression
expression = []
# to hold expression that contains image: word
result = []
index = 0
def extract_if(pattern, repl, index_group):
"""
extract the if statement to expression and replace it with special word in the text.
#index_in_expression_list#.
index_group is the position of the target if statement because we have two pattern.
repl contains {} to format the current index of extract if statement
"""
nonlocal text
nonlocal index
m = pattern.search(text)
while m:
expression.append(m.group(index_group))
text = pattern.sub(repl.format(index), text)
m = sub_if.search(text)
index += 1
return index
def build_if_statement(exp):
""" we have the index of exp in expression so keep building back the statement, this is only for nested statements"""
while get_if.search(exp):
exp = get_if.sub(lambda m: expression[int(m.group(1))], exp)
return exp
# extract all if statements
extract_if(sub_if, r'\1#{}#', 2)
extract_if(outer_if, r'#{}#', 0)
# for debugging
# print('\n\n\n'.join(expression))
result = [build_if_statement(exp) for exp in expression if 'image:' in exp]
# for debugging
# print('\n\n'.join(result))
# print(text) # if you need Order this will help with it just tell me so I can fix that.
return result
# Note this extract sub if and outer if if they both have image: word like [2,3]
print(('\n'+'-'*100+'\n').join(extract_image_if_statement(code)))
輸出:
{{- if .Values.k8swait.enabled [extract this 5]}}
some text ....
image: 000
{{- if [don't extract this sub if 6 ]}}
{{- end }}
{{- end }}
----------------------------------------------------------------------------------------------------
{{- if .Values.k8swait.enabled [extract this 4}}
some text ....
image:
{{- end }}
----------------------------------------------------------------------------------------------------
{{- if [extract this 3]}}
image: 000
{{- end }}
----------------------------------------------------------------------------------------------------
{{- if .Values.k8swait.enabled [extract this 2]}}
some text ....
image: 000
{{- if [extract this 3]}}
image: 000
{{- end }}
{{- end }}
----------------------------------------------------------------------------------------------------
{{- if .Values.k8swait.enabled [extract this 1}}
some text ....
image:
{{- end }}
如果if statements
的順序對您很重要,我們也可以解決這個問題,只需注釋您希望如何提取嵌套語句即可。 並且如果在嵌套if statements
的情況下,如果外部表達式有image:
word 並且子表達式也有那個詞,結果中我會提取兩個元素,如果你不想要的話,只需添加評論,我會修復它也。
我希望這可以幫助你好運。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.