user109447
user109447

Reputation: 1119

How to get lines between two patterns

I have a file like this:

a sth1
a sth2
b sth3
b sth4
c sth5
c sth6
c sth6
d sth8
d sth9
d sth10
X sth10
X sth11

and I woul'd like to recive all lines between first line starting with b and last line starting with d:

b sth3
b sth4
c sth5
c sth6
c sth6
d sth8
d sth9
d sth10

I have a sed command sed -n /"b"/,/"d"/p final.txt but the output is:

b sth3
b sth4
c sth5
c sth6
c sth6
d sth8

My question is how to modify sed command to get expected result ?

Im sorry for beeing not precise. I should ask about this:

I have a file like this:

127.0.0.1 - - [04/Jun/2014:11:21:01 +0200] STH1
127.0.0.1 - - [04/Jun/2014:11:21:01 +0200] STH2
127.0.0.1 - - [04/Jun/2014:11:21:01 +0200] STH3
127.0.0.1 - - [04/Jun/2014:12:21:01 +0200] STH4
127.0.0.1 - - [04/Jun/2014:12:21:01 +0200] STH5
127.0.0.1 - - [04/Jun/2014:12:21:01 +0200] STH6
127.0.0.1 - - [04/Jun/2014:12:21:01 +0200] STH7
127.0.0.1 - - [04/Jun/2014:13:21:01 +0200] STH8
127.0.0.1 - - [04/Jun/2014:13:21:01 +0200] STH9
127.0.0.1 - - [04/Jun/2014:13:21:01 +0200] STH10
127.0.0.1 - - [04/Jun/2014:14:21:01 +0200] STH11
127.0.0.1 - - [04/Jun/2014:14:21:01 +0200] STH12
127.0.0.1 - - [04/Jun/2014:15:21:01 +0200] STH13
127.0.0.1 - - [04/Jun/2014:15:21:01 +0200] STH14

and I want extract content between first line containing $startDate="04/Jun/2014:12:21:01" and last line containing $endDate="04/Jun/2014:13:21:01". The result should be:

127.0.0.1 - - [04/Jun/2014:12:21:01 +0200] STH4
127.0.0.1 - - [04/Jun/2014:12:21:01 +0200] STH5
127.0.0.1 - - [04/Jun/2014:12:21:01 +0200] STH6
127.0.0.1 - - [04/Jun/2014:12:21:01 +0200] STH7
127.0.0.1 - - [04/Jun/2014:13:21:01 +0200] STH8
127.0.0.1 - - [04/Jun/2014:13:21:01 +0200] STH9
127.0.0.1 - - [04/Jun/2014:13:21:01 +0200] STH10

$startDate and $endDate are variables in BASH script. I really apologise for my last post where I asked not precise question...

Upvotes: 1

Views: 108

Answers (7)

fedorqui
fedorqui

Reputation: 289495

If your file is unsorted, then it is necessary to loop twice: first to know the lines to print and then to print them:

$ awk 'FNR==NR {if (/^b/ && !b) {b=NR} if (/^d/) {d=NR}; next} (FNR>=b && FNR<=d)' file file
b sth3
b sth4
c sth5
c sth6
c sth6
d sth8
d sth9
d sth10

As per comments, if you want to define the b and d as a parameter you can use:

-v start="your_start_date"
-v end="your_end_date"

See an example with current data:

$ awk -v start="b" -v end="d" 'FNR==NR {if ($1 == start && !b) {b=NR} if ($1 == end) {d=NR}; next} (FNR>=b && FNR<=d)' file file
b sth3
b sth4
c sth5
c sth6
c sth6
d sth8
d sth9
d sth10

Based on your last update:

$ startDate="04/Jun/2014:12:21:01"
$ endDate="04/Jun/2014:13:21:01"

$ awk -v start="$startDate" -v end="$endDate" 'FNR==NR {if ($0 ~ start && !b) {b=NR} if ($0 ~ end) {d=NR}; next} (FNR>=b && FNR<=d)' file file
127.0.0.1 - - [04/Jun/2014:12:21:01 +0200] STH4
127.0.0.1 - - [04/Jun/2014:12:21:01 +0200] STH5
127.0.0.1 - - [04/Jun/2014:12:21:01 +0200] STH6
127.0.0.1 - - [04/Jun/2014:12:21:01 +0200] STH7
127.0.0.1 - - [04/Jun/2014:13:21:01 +0200] STH8
127.0.0.1 - - [04/Jun/2014:13:21:01 +0200] STH9
127.0.0.1 - - [04/Jun/2014:13:21:01 +0200] STH10

Upvotes: 0

Chandru
Chandru

Reputation: 1334

Use this sed command to get the expected result.

 $ sed -n '/^b/,/^d/{p;d};/^d/p' `input_filename`

Upvotes: 0

NeronLeVelu
NeronLeVelu

Reputation: 10039

sed -n '/^b/p;/^c/p;/^d/p' YourFile

assuming it is sort like your sample. take care of missing line with b or d

Upvotes: 0

Kent
Kent

Reputation: 195029

an awk one-liner

if your file is already sorted by the 1st column (the a, b, c...), this works for your example:

awk '$1>="b"&&$1<="d"' file

the "b" and "d" here could be other string, like abc and zzz as long as the file was sorted, it should work.

add a sed one-liner:

based on your example, this sed line worked here:

sed  -n '/^b/,/^d/{/^[^d]/p};/^d/p' file

Upvotes: 4

Mark Setchell
Mark Setchell

Reputation: 207365

If you don't mind grep:

grep "^[b-d]" file

Upvotes: 0

Jotne
Jotne

Reputation: 41446

Here is an awk

awk '/^b/ {f=1} /^d/ {g=1} g && !/^d/ {f=0} f' file
b sth3
b sth4
c sth5
c sth6
c sth6
d sth8
d sth9
d sth10

Upvotes: 0

anubhava
anubhava

Reputation: 784908

Here is a way you can do it in awk:

awk '/^b/{p=1} /^d/{p=2} p==2 && substr($1, 1, 1) != "d" {exit} p' file
b sth3
b sth4
c sth5
c sth6
c sth6
d sth8
d sth9
d sth10

Upvotes: 0

Related Questions