[etc]
in regex means any one of these characters, so it won't match a literal [etc]
.
with sed:
sed -zi '/\[etc\]\ntransient *= *true/!s|\(.*\)\(.*\)|\1\2[etc]\ntransient = true\n|' file
'/\[etc\]\ntransient *= *true/!
- checks whether the block
[etc]
followed bytransient = true
exists in the file.
- checks whether the block
transient *= *true
- Matches the string transient = true, with optional spaces around the = sign (* allows for zero or more spaces).
!
- This negates the match, so the subsequent replacement will only occur if the pattern is not found.
s|\(.*\)\(.*\)|\1\2[etc]\ntransient = true\n|
- The substitution part, which operates on the content that doesn’t match the pattern from above (![etc] block).
\1\2
- These are references to the parts of the input that were matched by the first two (.*) patterns:
\(.*\)
- captures any characters (except newline) before the matched pattern.
\(.*\)\1\2
- captures any characters (except newline) afterThese are references to the parts of the input that were matched pattern.by the first two
\(.*\)
patterns:
- captures any characters (except newline) afterThese are references to the parts of the input that were matched pattern.by the first two
[etc]\ntransient = true\n
- Will be inserted if the pattern is not found.
With grep/printf:
if ! grep -qPzo '\[etc\]\s*\n\s*transient\s*=\s*true' file; then
printf '%s\n%s\n' "[etc]" "transient = true" >> file
fi
Or with grep/ed:
if ! grep -qPzo '\[etc\]\s*\n\s*transient\s*=\s*true' file; then
ed -s file <<'EOF'
$a
[etc]
transient = true
.
w
q
EOF
fi
grep will check for the pattern and if it is not found ed will run:
-s
- tells ed to run in "silent" mode, suppressing most output.
$a
- appends text after the last line in the file.
.
- ed command to indicate the end of the text input.
w
- write the changes to the file.
q
- quit