Replace value in "key: value" statement, but only on first occurence of the key in the file
Another sed
alternative:
sed '1,/username/{/username/ s/:.*/:toto/};
1,/password/{/password/ s/:.*/:totopsw/}' infile
1,/regex/
start from the first line up-to first line that matched with given regex
(here it's username
string), change the "username"; doing the same for "password" part.
If your file is small enough to fit into memory, you can try reading the entire thing as a single record. That way, sed
will only make the substitution for the first time it sees the pattern on the "line" (record):
$ sed -Ez 's/(username:)[^\n]*/\1toto/; s/(password:)[^\n]*/\1totopsw/' file.yaml
spring:
datasource:
url: url
username:toto
password:totopsw
api:
security:
username:foo
password: foopwd
To make the change in the original file, just add -i
:
sed -i -Ez 's/(username:)[^\n]*/\1toto/; s/(password:)[^\n]*/\1totopsw/' file.yaml
If the file is longer, here is an awk
-based solution that processes it line-wise:
awk '/^[[:space:]]+username/ && !u_chng{sub(/:.+$/,": toto"); u_chng=1}
/^[[:space:]]+password/ && !p_chng{sub(/:.+$/,": totospw"); p_chng=1} 1' input.yml
This will check each line whether it starts with username
or password
, respectively. If so, and the associated flags u_chng
and p_chng
are not yet set, it sets the value after the :
to your new desired one and sets the respective flag so that any further occurrences of these keywords are disregarded.
Result:
spring:
datasource:
url: url
username: toto
password: totospw
api:
security:
username:foo
password: foopwd
Note that if you use an awk
implementation that doesn't understand character classes ([[:space:]]
), change
/^[[:space:]]+username/
to
/^[ \t]+username/