簡體   English   中英

使用正則表達式檢測具有 if 語句的 jinja2 變量 - python

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM