0

Below is my file

$ cat README
login user1
run .profile
cd /u/opt
unzip -l zip file
copy files in zip file to .orig
unzip -o the zip file
cd /u/opt/install
./reqe21.sh
sqlplus admin/<password> @req.sql
logout

I need lines between the matched string last unzip and logout i.e desired output is below

cd /u/opt/install
./reqe21.sh
sqlplus admin/<password> @req.sql

I need a couple of answers.

  1. When I tried sed -n '/unzip -o /,/logout/p' README it does not exclude the matching lines.

Thus, I get the below output:

unzip -o the zip file
cd /u/opt/install
./reqe21.sh
sqlplus admin/<password> @req.sql
logout

I tried another solution given here: How can I exclude the lines which matche the range patterns in sed?

But, I do not get the desired output. See below:

$ sed '1,/unzip/d;/logout/,$d' README
copy files in zip file to .orig
unzip -o the zip file
cd /u/opt/install
./reqe21.sh
sqlplus vrcadmin/<password> @req.sql
  1. How do I use sed so that I get the lines between last unzip and the last logout i.e the desired output as was shared before.
Freddy
  • 25,565
Ashar
  • 491
  • @Quasímodo No. I tried the solution and it does not give me the desired results. Updated my Question as well. Please check – Ashar Jan 08 '21 at 20:16
  • Yes, it does, as long as you keep the whole initial pattern you had tried. sed '1,/unzip -o /d;/logout/,$d' – Quasímodo Jan 08 '21 at 20:18
  • It answers my question partially. i.e when I give unzip -o However, how can I get it to consider the last unzip line when I simply give unzip and not unzip -o ? – Ashar Jan 08 '21 at 20:21
  • 1
    That is a different question. For those additional complications, I'd use Awk or feed Sed the file from upside down with Tac. – Quasímodo Jan 08 '21 at 20:23

3 Answers3

4

This simply isn't a job that sed is best for. Try this:

$ tac file | awk '/unzip/{exit} f; /logout/{f=1}' | tac
cd /u/opt/install
./reqe21.sh
sqlplus admin/<password> @req.sql

or if you prefer to use just one tool for some reason:

$ awk '/logout/{f=0} f{rec=rec $0 ORS} /unzip/{rec=""; f=1} END{printf "%s", rec}' file
cd /u/opt/install
./reqe21.sh
sqlplus admin/<password> @req.sql
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
Ed Morton
  • 31,617
0

Inverting the input and then running sed on it. Using the range operator we select the block and then trim the boundaries by reapplying the same regex.

$ tac |
sed -e '/logout/,/unzip/!d;//!d' |
tac
cd /u/opt/install
./reqe21.sh
sqlplus admin/<password> @req.sql

Or, if we want the result w/o any other utility. we keep accumulating the block (bounded by unzip and logout) in the hold space. Then overwrite hold if we see an unzip line again.Th7s will get us the last unzip to logout bounded block. Then we clip the boundaries.This is all Posixly sed

sed -e '
  /\n/{
    P;/\n.*\n/D;d
  }
  /unzip/,/logout/!d
  H;/unzip/h;/logout/!d
  g;D
' file
guest_7
  • 5,728
  • 1
  • 7
  • 13
0
tac filename| awk '/logout/{f=1}/unzip/{f=0}f && !/logout/'|tac

output

cd /u/opt/install
./reqe21.sh
sqlplus admin/<password> @req.sql