sarjaana
sarjaana

Reputation: 85

Search segment and append value at the end

In a file I want to append a string after the specific segment with key "sys-mgmt-agent". This is the file content:

  sys-mgmt-agent:
    networks:
     edgex-network:
       aliases:
           - edgex-sys-mgmt-agent
    depends_on:
      - redis
    volumes:
      - /proc/uptime:/proc/uptime
      - /var/log/auth.log:/var/log/auth.log
      - ${HOST_SECURITY_FILE_PATH}edgex-redis:/tmp/edgex/secrets/edgex-redis:z

  edge-orchestrator:
    networks:
     edgex-network:
       aliases:
           - edgex-sys-mgmt-agent
    depends_on:
      - redis
    volumes:
      - /proc/uptime:/proc/uptime
      - /var/log/auth.log:/var/log/auth.log
      - ${HOST_SECURITY_FILE_PATH}edgex-redis:/tmp/edgex/secrets/edgex-redis:z

This is the expected result:

  sys-mgmt-agent:
    networks:
     edgex-network:
       aliases:
           - edgex-sys-mgmt-agent
    depends_on:
      - redis
    volumes:
      - /proc/uptime:/proc/uptime
      - /var/log/auth.log:/var/log/auth.log
      - ${HOST_SECURITY_FILE_PATH}edgex-redis:/tmp/edgex/secrets/edgex-redis:z
    MY STRING

  edge-orchestrator:
    networks:
     edgex-network:
       aliases:
           - edgex-sys-mgmt-agent
    depends_on:
      - redis
    volumes:
      - /proc/uptime:/proc/uptime
      - /var/log/auth.log:/var/log/auth.log
      - ${HOST_SECURITY_FILE_PATH}edgex-redis:/tmp/edgex/secrets/edgex-redis:z

I found the segment using sed command: sed -n '/sys-mgmt-agent:/,/^\s*$/p' <file> but I can't append my string.

Upvotes: 2

Views: 98

Answers (3)

markp-fuso
markp-fuso

Reputation: 35146

A sed idea that builds on OPs sed attempt:

$ mystring='MY STRING'
$ sed "/sys-mgmt-agent:/,/^$/{/^$/i\    ${mystring}
}" mydata

Where:

  • /sys-mgmt-agent/,/^$/ - range to search for
  • {...} - commands to apply to matching range
  • /^$/i\ ${mystring} - at the blank line insert a new line " MY STRING"

NOTE: The i\ ${mystring} can't have anything after it on the same line hence the 2-line solution; I'm open to suggestions on how to collapse this into a single line.


UPDATE: @potong's suggestion for using -e flags to piece together a one-line solution works with the addition of double quotes around ${mystring}:

$ mystring='MY STRING'
$ sed -e '/sys-mgmt-agent:/,/^$/{/^$/i\    '"${mystring}" -e '}' mydata

The above generates:

  sys-mgmt-agent:
    networks:
     edgex-network:
       aliases:
           - edgex-sys-mgmt-agent
    depends_on:
      - redis
    volumes:
      - /proc/uptime:/proc/uptime
      - /var/log/auth.log:/var/log/auth.log
      - ${HOST_SECURITY_FILE_PATH}edgex-redis:/tmp/edgex/secrets/edgex-redis:z
    MY STRING

  edge-orchestrator:
    networks:
     edgex-network:
       aliases:
           - edgex-sys-mgmt-agent
    depends_on:
      - redis
    volumes:
      - /proc/uptime:/proc/uptime
      - /var/log/auth.log:/var/log/auth.log
      - ${HOST_SECURITY_FILE_PATH}edgex-redis:/tmp/edgex/secrets/edgex-redis:z

Upvotes: 1

potong
potong

Reputation: 58488

This might work for you (GNU sed):

sed '/sys-mgmt-agent:/{:a;/:$/h;n;/\S/{$!ba;p};x;s/\S.*/MY STRING/p;x;$d}' file

N.B. if MY STRING contains /'s these must be escaped/quoted i.e. \/. This also indents to the depth of the last stanza.

Upvotes: 2

markp-fuso
markp-fuso

Reputation: 35146

Assumptions:

  • OP insists on using basic commands avialable under bash
  • input is nicely formatted as presented
  • if sys-mgmt-agent: shows up more than once the desired string is to be appended to each segment
  • there is at least one blank line between segments

One awk solution:

$ mystring="MY STRING"                         # string to be appended to segment
$ awk -v ms="${mystring}" '                    # pass ${mystring} as awk variable "ms" 
/sys-mgmt-agent:/ { foundit=1 }                # if line contains "sys-mgmt-agent:" then set our flag
/^$/ && foundit { printf "    %s\n\n", ms      # if blank line and foundit=1 then print our string plus a new blank line
                  foundit=0                    # reset our flag
                  next                         # go to next input line
                }
                { print }                      # print all other lines as is
' mydata                                       # assuming input data is in file named "mydata"

The above generates:

sys-mgmt-agent:
  networks:
   edgex-network:
     aliases:
         - edgex-sys-mgmt-agent
  depends_on:
    - redis
  volumes:
    - /proc/uptime:/proc/uptime
    - /var/log/auth.log:/var/log/auth.log
    - ${HOST_SECURITY_FILE_PATH}edgex-redis:/tmp/edgex/secrets/edgex-redis:z
  MY STRING

edge-orchestrator:
  networks:
   edgex-network:
     aliases:
         - edgex-sys-mgmt-agent
  depends_on:
    - redis
  volumes:
    - /proc/uptime:/proc/uptime
    - /var/log/auth.log:/var/log/auth.log
    - ${HOST_SECURITY_FILE_PATH}edgex-redis:/tmp/edgex/secrets/edgex-redis:z

Upvotes: 0

Related Questions