1

I have a bash script that edits two tags in a yaml file and these values are passed as parameters. How can I change the script for a scenario where only one tag has to be updated

#!/bin/bash

#Update UI-ImageTag
sed -i -e '/APP:/{n;n;s/\(imageTag\).*/\1: "'"app-ui-$1"'" /}' \
       -e '/APP:/{n;n;n;n;s/\(imageTag\).*/\1: "'"app-db-$2"'" /}' \
       values.yaml

While running the script and passing values for parameters $1 and $2 Ex(./script.sh 1.0 2.0) both the tags are updated in the values.yaml file, but when I give value for only one parameter and leave the other one empty(i.e., execute the script by passing value for $1 only), then the $2 tag in values.yaml file is replaced with an empty value. How to change the script so that in a scenario where I dont need to change the tag of app-db and if I dont pass a value for $2, it keeps the old value in the yaml file unchanged

kr_devops
  • 117
  • 3
  • 14
  • Does this answer your question? [Check number of arguments passed to a Bash script](https://stackoverflow.com/questions/18568706/check-number-of-arguments-passed-to-a-bash-script) – GhostCat Apr 01 '22 at 08:53
  • Any such script should **check** for the number of arguments passed to it, and depending on that number either give an error message, or well, do the right thing. – GhostCat Apr 01 '22 at 08:54
  • A job for https://github.com/mikefarah/yq – Diego Torres Milano Apr 01 '22 at 18:47

2 Answers2

1

You can ask the shell to supply a default value when something is unset, and just change your sed script to capture the old value and replace with that, so that you effectively don't change anything.

#!/bin/bash
sed -i -e '/APP:/{n;n;s/\(imageTag\).*/\1: "'"app-ui-$1"'" /}' \
       -e '/APP:/{n;n;n;n;s/\(imageTag\)\(.*\)/\1: "'"${2+app-db-}${2-\\2}"'" /}' \
       values.yaml

The parameter expansion ${2+value} expands to value only if $2 is set, and ${2-\\2} expands to \2 when it is unset, and to its value when it's set. You'll notice that the regex was also changed slightly to capture the text after imageTag into \2 for this purpose.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • It is working fine when $2 is not set, but when I pass a value for $2 it is taking the value twice. Example If I pass $2 value as 2.0 the the result is giving as "app-db-2.02.0" But instead I want something like app-db-2.0 – kr_devops Apr 01 '22 at 10:09
  • Oops, thanks for the bug report; updated. – tripleee Apr 02 '22 at 07:04
0

Suggesting try awk script:

awk '
/APP:/{skip2 = 3; skip4 = 5}
!skip2 && inp1 {$0 = gensub("(imageTag)","\\1: \"app-ui-"inp1"\" \\\\",1)}
!skip4 && inp2 {$0 = gensub("(imageTag)","\\1: \"app-db-"inp2"\" \\\\",1)}
{print; --skip2; --skip4}
' inp1="$1" inp2="$2" values.yaml > values.yaml.1
mv values.yaml.1 values.yaml

Not tested, not provided sample data.

Explanation:

awk ' # start awk script
/APP:/ { # for evey line matching RegExp /APP:/ set down counter to skipped line
  skip2=3; # set skip2 action to next 2 lines including this is 3
  skip4=5; # set skip4 action to next 4 lines including this is 5
}
skip2 == 0 && inp1 { # in current line, if skip2 reached 0, and variable inp1 exist
  $0 = gensub("(imageTag)","\\1: \"app-ui-"inp1"\" \\\\",1); # do string subtition using gensub functin on current line.
}
skip4 == 0  && inp2 { # in current line, if skip4 reached 0, and variable inp2 exist
  $0 = gensub("(imageTag)","\\1: \"app-db-"inp2"\" \\\\",1); # do string subtition using gensub functin on current line.
}
{  # on every line
  print $0; # print current line
  --skip2;  # decrement skip2
  --skip4;  # decrement skip4
}' \  # end awk script
inp1="$1" \  # assign 1st script argument to awk variable inp1
inp2="$2" \  # assign 2nd script argument to awk variable inp1
values.yaml > values.yaml.1 # redirect output to values.yaml.1
mv values.yaml.1 values.yaml # override output to values.yaml
Dudi Boy
  • 4,551
  • 1
  • 15
  • 30