I am looking at replacing some indented lines in a Yaml file using sed.
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
Yaml is strict about its indentation and will want to know how I can accomplish a replacement of the text after example "limits:"
I have tried '0,/cpu:.*m/s//cpu: 900m/'
and '/limits:/!b;n;s//ccpu: 900m'
'0,/cpu:.*m/s//cpu: 900m/'
outputs:
resources:
limits:
cpu: 900m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
The only issue I have with this is I will want to specify the replacement should be done on the example CPU for limits and not for the requests.
So I tried '/limits:/!b;n;s//ccpu: 900m'
which outputs:
resources:
limits:
cpu: 900m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
Notice how it is not properly indented? How can I achieve this by leaving the indentation as it is and also if I can specify 1st and 2nd lines after "limits:" or "requests:" that will be nice.
CodePudding user response:
If you cannot install yaml parsing tools such as yq
, you can use this gnu-sed
solution:
sed -E '/limits:/!b;n;s/^([[:blank:]]*cpu: ).*/\1900m/' file.yml
resources:
limits:
cpu: 900m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
Breakdown:
/limits:/!b
: Search for textlimits:
otherwise branch to end of scriptn
: Read/append the next line of input into the pattern spaces/.../.../
: Do this substitution^
: Match start([[:blank:]]*cpu: )
: Match 0 or more whitespaces followed by textcpu:
. Capture this in capture group #1.*
: Match remaining text till end of line/\1900m/
: Replace with back-reference of capture group #1 i.e.\1
followed by new value900m
CodePudding user response:
With your shown samples and in GNU awk
you can try following awk
code. Though tools which know yaml files are recommended in case they can't be used this will be helpful.
awk -v RS="^$" '
match($0,/(^|\n)([[:space:]] resources:\n[[:space:]] limits:\n[[:space:]] cpu: )[^\n] (\n.*)$/,arr){
printf("%s",arr[1] arr[2] "900m" arr[3])
}
' Input_file
Here is the Online Demo for used regex (^|\n)([[:space:]] resources:\n[[:space:]] limits:\n[[:space:]] cpu: )[^\n] (\n.*)$
adding it here for better understanding for regex.
Explanation:
(^|\n)
: Creating 1st capturing group which matches either starting of value OR new line.([[:space:]] resources:\n[[:space:]] limits:\n[[:space:]] cpu: )
: Creating 2nd capturing group which matches spaces followed by resources followed by new line followed by spaces followed by limits: followed by new line followed by spaces cpu:[^\n]
: Matching everything before new line.(\n.*)$
: Creating 3rd capturing group new lines followed by everything till end of line.
CodePudding user response:
Using any awk:
$ awk 'f{sub(/[^ ] $/,"900m"); f=0} /limits:/{f=1} 1' file
resources:
limits:
cpu: 900m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi