Sed problem with word on beginning of line and a multilines search

Viewed 38

I have a text file with the below text on multiple places:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: harbor-exporter
  labels:
    release: mgmt

I want to have:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: harbor-exporter
  namespace: test
  labels:
    release: mgmt

Because this text is present on multiple places in the file, I do need to search for: metadata:\n name:harbor-exporter and append the line namespace: test. Next to that, the metadata: should be present at the beginning of the line. What is the best way of achieving this with sed?

I have tried:

cat harbor-exporter.yaml | sed ':a;N;$!ba;s|metadata:\n  name: harbor-exporter|NewString|g'

But I do need the word metadata: at the start of a line. So I put a ^ in front of metadata: and that failing.

Command which is failing:

cat harbor-exporter.yaml | sed ':a;N;$!ba;s|^metadata:\n  name: harbor-exporter|NewString|g'

Thanks

2 Answers

This might work for you (GNU sed):

sed -E ':a;/metadata:/{n;/name: harbor-export/!ba;p;s/\S.*/namespace: test/}' file

Match on a line containing metadata, print it and fetch the next line. If that line does not contain name: harbor-export, start again. Otherwise, print that line and replace it with namespace:test.

Tested on GNU sed, not sure if this requires changes on other implementations: If metadata: cannot occur in consecutive lines, the logic can be simplified:

sed '/^metadata:$/{n; s/^  name: harbor-exporter$/&\n  namespace: test/}'
  • /^metadata:$/ if whole line content is metadata:
    • n fetch next line (pattern space is replace with this new line)
    • s/^ name: harbor-exporter$/&\n namespace: test/ add required line if the next line so fetched has the content name: harbor-exporter

Also, you might be better off with a tool that understands YAML such as https://github.com/TomWright/dasel

Related