AVJ
AVJ

Reputation: 188

Replace value of line in yml with Bash

I have yml file in below format.

Backendapp:
  Name: spring-rest 
  Image: "testuser/backend"
  ImageTag: "latest"
  ImagePullPolicy: "Always"
  Port: 8080
  replicaCount: 2

Frontendapp:
  Name: spring-js
  Image: "testuser/frontend"
  ImageTag: "latest"
  ImagePullPolicy: "Always"
  replicaCount: 2

How to replace 'Image', 'ImageTag' for Backendapp through Bash?

Edit: say file name is test.yml with above contents. Then, I would like to replace 'Image' and 'ImageTag' with some another value(say 'teststring','latest2' resp.) for 'Backendapp' part.

Modified file should look like below.

Backendapp:
  Name: spring-rest 
  Image: "teststring"
  ImageTag: "latest2"
  ImagePullPolicy: "Always"
  Port: 8080
  replicaCount: 2

Frontendapp:
  Name: spring-js
  Image: "testuser/frontend"
  ImageTag: "latest"
  ImagePullPolicy: "Always"
  replicaCount: 2

Upvotes: 1

Views: 3929

Answers (3)

RavinderSingh13
RavinderSingh13

Reputation: 133428

Following awk may help you on same:

awk '
/:$/{
  flag=""
}
/Backendapp/||/Frontendapp/{
  flag=1
}
flag && NF && (/Image:/||/ImageTag:/){
  match($0,/^[[:space:]]+/);
  val=substr($0,RSTART,RLENGTH);
  $NF="teststring";
  print val $0;
  next
}
1
'   Input_file

Output will be as follows:

Backendapp:
  Name: spring-rest
  Image: teststring
  ImageTag: teststring
  ImagePullPolicy: "Always"
  Port: 8080
  replicaCount: 2

Frontendapp:
  Name: spring-js
  Image: teststring
  ImageTag: teststring
  ImagePullPolicy: "Always"
  replicaCount: 2

Solution 2nd: As per OP, OP needs to have shell variable into awk variable too then following may help on same:

awk -v val_shell="$shell_variable" '
/:$/{
  flag=""
}
/Backendapp/||/Frontendapp/{
  flag=1
}
flag && NF && (/Image:/||/ImageTag:/){
  match($0,/^[[:space:]]+/);
  val=substr($0,RSTART,RLENGTH);
  $NF=val_shell;
  print val $0;
  next
}
1
'   Input_file

Upvotes: 2

Desmond McCarter
Desmond McCarter

Reputation: 31

Here's your solution. It basically uses SED to do the replacement. Just copy and paste the bits between "START OF SCRIPT" and "END OF SCRIPT" into any bash script then run (simple instructions below):

START OF SCRIPT ...

#!/bin/bash

# SED script will be stored here ...

sedscript=/tmp/sedscript.sed

# first argument to script is the parent name ...

parent="${1}"

# second argument to the script is child name...

child="${2}"

# third argument is the value to replace the CHILD value with ...

value="$3"

cat << EOF > "${sedscript}"

# find parent ...
/^${parent}:.*$/{

    p

    # load next line into input ...
    n

    # another parent found to print it ...
    /^[a-z|A-Z|0-9]\{1\}:.*$/{

        # we have found another parent
        # so stop processing ...

        b print_default_text
    }

    :search_for_child

    /^[ |   ]*$child[ | ]*:.*$/{

        s/^\([^:]*:[ |\"|   ]*\)[^\"]*\(.*\)$/\1$value\2/p

        b dont_print_default_text
    }

    p
    n
    b search_for_child
}


:print_default_text
p

:dont_print_default_text

EOF

sed -n -f "${sedscript}" "input.yml"

... END OF SCRIPT

Now we save the script as alter.sh (for example) then run it like this (changing the Frontendapp/Image to "another-image-name"):

./alter.sh Frontendapp Image "another-image-name"

INPUT FILE ....

Backendapp: Name: spring-rest Image: "teststring" ImageTag: "latest2" ImagePullPolicy: "Always" Port: 8080 replicaCount: 2

Frontendapp: Name: spring-js Image: "testuser/frontend" ImageTag: "latest" ImagePullPolicy: "Always" replicaCount: 2

Output file ....

Backendapp: Name: spring-rest Image: "teststring" ImageTag: "latest2" ImagePullPolicy: "Always" Port: 8080 replicaCount: 2

Frontendapp: Name: spring-js Image: "another-image-name" ImageTag: "latest" ImagePullPolicy: "Always" replicaCount: 2

Note: the script takes care of quotes too, i.e. if the original value has quotes then the new value will be surrounded in quotes also.

Hope this helps ....

Upvotes: 2

RomanPerekhrest
RomanPerekhrest

Reputation: 92854

Awk solution:

awk 'NF==1 && /^[^[:space:]]+:/{ f=(/^(Back|Front)endapp:/) }
     f && $1 ~ /^Image(Tag)?:/{ $1="  teststring" }1' test.yml

The output:

Backendapp:
  Name: spring-rest
  teststring: "testuser/backend"
  teststring: "latest"
  ImagePullPolicy: "Always"
  Port: 8080
  replicaCount: 2

Frontendapp:
  Name: spring-js
  teststring: "testuser/frontend"
  teststring: "latest"
  ImagePullPolicy: "Always"
  replicaCount: 2

Upvotes: 1

Related Questions