Not much familiar with sed, I'm trying to delete 2 lines before a pattern (a timeout value and an empty line) and then reinsert both lines with updated timeout.
Here's a part of the yaml file that I've:
- id: phase1
blahblahbal
timeout: 720
- id: phase2
blahblahbalh
timeout: 1800
I'm trying to update first timeout to '900'.
Here's what I've with grep:
grep -v "$(grep -B 2 'id: phase2' test.yaml | grep -v 'id: phase2')" test.yaml > test.yaml
and then inserting updated value with sed. This is working but the grep doesn't look nice. Is there a way to delete the two lines with sed before a pattern?
Expected output after first sed/grep:
- id: phase1
blahblahbal
- id: phase2
blahblahbalh
timeout: 1800
Expected output final:
- id: phase1
blahblahbal
timeout: 900
- id: phase2
blahblahbalh
timeout: 1800
This is how it could be done using awk ( back-replace2.awk
):
$1 ~ /timeout:/ { lineTimeOut = NR }
/^[ \t\r]*$/ { lineEmpty = NR }
/- id: phase2/ {
if (lineTimeOut == NR - 2 && lineEmpty == NR - 1) {
buf1 = " timeout: 900"
}
}
{
if (NR > 2) { print buf1 }
buf1 = buf2 ; buf2 = $0
}
END {
if (NR >= 2) { print buf1 }
if (NR >= 1) { print buf2 }
}
The line numbers of a timeout:
line and an empty line are remembered. Thus, it can be checked whether these lines appeared exactly two lines before / one line before the line where the remarked pattern (here - id: phase2
) matches.
The variables buf1
and buf2
are used to make some kind of cycle buffering (ie the third last line is echoed for every line).
Therefore, the END
rule is necessary to echo the rest of input (the contents of cycle buffers).
Test:
$ cat >back-replace2.txt <<EOF
- id: phase1
blahblahbal
timeout: 720
- id: phase2
blahblahbalh
timeout: 1800
EOF
$ awk -f back-replace2.awk back-replace2.txt
- id: phase1
blahblahbal
timeout: 900
- id: phase2
blahblahbalh
timeout: 1800
$
Notes:
I didn't check the edge cases (eg whether files with less than 3 lines are handled correctly).
The pattern matching and replacement may need additional logic. I'm sure the questioner will be able to adjust the script appropriately.
Here is my solution with sed:
# Remove above two lines before phase2 id
sed -i ':a;N;s/\n/&/2;Ta;/\n- id\: phase2$/s/.*\n//;P;D' test.yaml
# Add updated timeout
sed -i "/- id\: phase2/ i\\
timeout: 900\\
" test.yaml
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.