3

This sed expression works, but is there a better way to represent the white space in both the search pattern and replace string?

BRANCHTAG=7.17.9-main-5ee3e99d5ff002862d93728d821461033de1186d
PRIOR_VERSION=7.17.4
clear; sed "s/^    newTag: ${PRIOR_VERSION}.*$/    newTag: ${BRANCHTAG}/" kustomization.yaml

I cannot just search on newTag as that would replace all newTag strings in the file

1 Answers1

3

Assuming you want to allow any number of blanks (spaces or tabs) at the start of the line and that you want to keep these:

sed "s/^\([[:blank:]]*newTag:\) $PRIOR_VERSION.*/\1 $BRANCHTAG/" kustomization.yaml

This uses a back-reference to insert the matched blanks and the key itself in the replacement part of the sed expression. The new value is then inserted after that.

It is assumed that the value in $BRANCHTAG does not contain the character &, literal newlines, or the slash or backslash character (these would need to be escaped separately).

It is assumed that the value in $PRIOR_VERSION is a regular expression that does not contain slashes. Since it's interpreted as a regular expression, dots (for example) need to be escaped.

See also How to ensure that string interpolated into `sed` substitution escapes all metachars

But since you're dealing with a YAML file, it would be safer to use a proper YAML parser, such as yq (from https://kislyuk.github.io/yq/):

yq -y --arg oldval "$PRIOR_VALUE" --arg newval "$BRANCHTAG" \
    'if .newTag == $oldval then .newTag |= $newval else . end' kustomization.yaml

This assumes that newTag is a top-level key in the YAML document and would replace the key's value with the value passed into $newval on the command line as the argument to --arg if it's current value is $oldval. This value would additionally be properly quoted and encoded by the yq parser (assuming it's a common UTF-8 string). There is no issue with the values containing newlines, backslashes or other characters that may have been problematic with sed.

yq can do in-place edits using its --in-place (or -i) option.

Kusalananda
  • 333,661
  • 1
    [[:blank:]] usually matches a lot more blank characters than just space or tab, though in a yaml file, you're unlikely to find any other ones than space and tab. – Stéphane Chazelas Apr 18 '22 at 10:34
  • sorry I should have passed in 7.17.4 as a variable – Paul Maxfield Apr 18 '22 at 10:48
  • 1
    so yq would be the correct tool to use in this circumstance and editing yaml files? – Paul Maxfield Apr 18 '22 at 10:58
  • 1
    @PaulMaxfield In my view, yes. As soon as you deal with files in any structured format, such as YAML, JSON, XML, TOML, etc., line-oriented tools like sed can probably do some of the naive editings, but they don't know anything about the restrictions, requirements, and structure that these formats have. Also, injecting shell variables into GNU sed specifically is dangerous, unless you have full control over the contents of those variables. – Kusalananda Apr 18 '22 at 11:02
  • @Kusalananda thank you for your help – Paul Maxfield Apr 18 '22 at 13:43