awk 在第 n 次出现后插入缩进

awk to insert after nth occurrence with indentation

我正在尝试编辑缩进很重要的 yaml 文件。下面是输入

spec:
  replicas: 1
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp
      app.kubernetes.io/instance: myapp
  template:
    metadata:
      annotations:
        checksum/config: 2cee4a874d2afd91d92301f15efece5afbca3abc63ba3b2b
        checksum/tls-secrets: 649c0580ebbcf3ae194d17b8ac4cc2f1cda33f145da9764
      labels:
        app.kubernetes.io/name: myapp
        app.kubernetes.io/instance: myapp
    spec:
      serviceAccountName: myapp-acc
      containers:
        - name: myapp-pod
          image: "imagerepo"
          resources:
            requests:
              cpu: 500m
              memory: 800Mi

我想在 yaml 文件中第 11 次出现的“resources:”和文件中第 1 次出现的“serviceAccountName:”之后插入相应的数据缩进。我的意思是无论缩进搜索模式有什么,我们都可以相应地调整插入文本的缩进资源之后:我想要

    limits:
      cpu: 500m
      memory: 800Mi

serviceAccountName

之后
  imagePullSecrets:
    - name: imagepullsecret

输出文件

spec:
  replicas: 1
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp
      app.kubernetes.io/instance: myapp
  template:
    metadata:
      annotations:
        checksum/config: 2cee4a874d2afd91d92301f15efece5afbca3abc63ba3b2b
        checksum/tls-secrets: 649c0580ebbcf3ae194d17b8ac4cc2f1cda33f145da9764
      labels:
        app.kubernetes.io/name: myapp
        app.kubernetes.io/instance: myapp
    spec:
      serviceAccountName: myapp-acc
      imagePullSecrets:
        - name: imagepullsecret
      containers:
        - name: myapp-pod
          image: "imagerepo"
          resources:
            limits:
              cpu: 500m
              memory: 800Mi
            requests:
              cpu: 500m
              memory: 800Mi

你应该为此使用专用的 yaml 解析器,例如 yq,但如果你出于某种原因不能使用它:

awk '/resources:/ { mrk=1;print;match([=10=],"resources:");srt=RSTART;next } mrk==1 { for(i=1;i<=srt+1;i++) { printf " " };printf "limits:\n";for(i=1;i<=srt+3;i++) { printf " " };printf "cpu: 500m\n";for(i=1;i<=srt+3;i++) { printf " " };printf "memory: 800Mi\n";mrk=0 }1' yamlfile

解释:

awk '/resources:/ {                                        # Process resources tag
            mrk=1;                                         # Set marker variable to 1
            print;                                         # Print line
            match([=11=],"resources:");                        # Find where "resources:" is in the line
            srt=RSTART;                                    # Store the location in srt variable
            next                                           # Skip to next line
            } 
     mrk==1 {                                              # Process next line after resources:
            for(i=1;i<=srt+1;i++) { 
               printf " " };                               # Use srt to print leading spaces
               printf "limits:\n";                         # Print limits tags
               for(i=1;i<=srt+3;i++) { 
                  printf " "                               # Do the same for cpu
               };
               printf "cpu: 500m\n";
               for(i=1;i<=srt+3;i++) { 
                 printf " "                                # Do the same for mem
               };
               printf "memory: 800Mi\n";
               mrk=0 
            }1' yamlfile

请注意,此解决方案取决于规范中是否存在任何其他 containers/resources,这可能是也可能不是。

$ cat tst.awk
{ print }
sub(/serviceAccountName:.*/,"") && (++cnt1 == 1) {
    print [=10=] "imagePullSecrets:"
    print [=10=] "  - name: imagepullsecret"
}
sub(/resources:.*/,"") && (++cnt2 == 11) {
    print [=10=] "  limits:"
    print [=10=] "    cpu: 500m"
    print [=10=] "    memory: 800Mi"
}

$ awk -f tst.awk file
spec:
  replicas: 1
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp
      app.kubernetes.io/instance: myapp
  template:
    metadata:
      annotations:
        checksum/config: 2cee4a874d2afd91d92301f15efece5afbca3abc63ba3b2b
        checksum/tls-secrets: 649c0580ebbcf3ae194d17b8ac4cc2f1cda33f145da9764
      labels:
        app.kubernetes.io/name: myapp
        app.kubernetes.io/instance: myapp
    spec:
      serviceAccountName: myapp-acc
      imagePullSecrets:
        - name: imagepullsecret
      containers:
        - name: myapp-pod
          image: "imagerepo"
          resources:
            limits:
              cpu: 500m
              memory: 800Mi
            requests:
              cpu: 500m
              memory: 800Mi

我在最初 运行 提供示例输入的代码后添加了 ++cnt 测试,因为该输入不提供测试该功能的方法。