site  contact  subhomenews

sed one-liner to extract lines between two patterns

February 14, 2022 — BarryK

EasyOS inserts lines between two patterns, in file /root/.jwmrc-tray, as explained in the previous post:

https://bkhome.org/news/202202/changes-needed-to-fix-jwmdesk.html

...shows the script that inserts between "STARTICONS" and "ENDICONS".

It seemed OK to me, and works OK for me, tested on three different computers, however keef reported this:

https://forum.puppylinux.com/viewtopic.php?p=49760#p49760

...the "</JWM>" closing tag is not at the end of .jwmrc-tray. It seems that in keef's case, multi-threading has resulted in the file being written to out-of-order.

So, what we need is to make that insertion an atomic operation, preferably done as a one-liner.

Before considering how to do that, what about the reverse situation? if the user edits /etc/uimanager and changes back to icon-on-desktop, when X starts, /root/.xinitrc calls a script that will remove all lines between "STARTICONS" and "ENDICONS" in /root/.jwmrc-tray. That script is also going to be subject to the potential out-of-order writing problem.

Extracting of lines between two patterns, as a sed or awk on-liner, is well documented, for example here:

https://catonmat.net/sed-one-liners-explained-part-three

Like this:

# sed -i '/STARTICONS/,/ENDICONS/d' /root/.jwmrc-tray

...nice, but it also deletes the start and end patterns. I want to keep the lines with those patterns!

I hunted around, and found a solution:

https://unix.stackexchange.com/questions/88382/using-sed-to-delete-everything-between-two-words

...which has made me realise just how superficial my knowledge of sed is. Here is the solution:

# sed '/STARTICONS/,/ENDICONS/{/STARTICONS/!{/ENDICONS/!d}}' /root/.jwmrc-tray

...instead of just the "d", extra conditions can be applied to exclude the start and end patterns.

Fascinating!

EDIT:
Was going to do it as a separate post, but the opposite, to insert lines between two patterns is a pretty simple sed one-liner, just appending to this post...

I have been reading this sed tutorial:

https://www.grymoire.com/Unix/Sed.html

OK, I haven't understood everything in that page, but it seems the way to insert text between two patterns, if the text is in a file:

# sed -i -e '/STARTICONS/,/ENDICONS/{/STARTICONS/!{/ENDICONS/!d}}' -e '/STARTICONS/r newtext.txt' /root/.jwmrc-tray

...firstly, have to remove anything pre-existing between the two patterns, then insert the new text. I cannot see how to do this as one expression, hence the two "-e" expressions.

Well, it is still a one-liner, so I expect that the operation on /root/.jwmrc-tray will be atomic.        

Tags: easy