Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Print the section from a file from sed except first or last line

2 views
Skip to first unread message

#! /shell/nerd

unread,
Nov 18, 2009, 6:14:11 PM11/18/09
to
HI,

sed '/AAA/,/BBB/p' <file> gives me

AAA
some text
some text
BBB


Now I want is the out put without AAA or BBB. How is this possible
with a single sed command? I tried following but didn't work -
sed '/AAA/,/BBB/{ 1d; $d; p; }' <file>

Chris F.A. Johnson

unread,
Nov 18, 2009, 6:25:05 PM11/18/09
to

sed -e '1,/AAA/d' -e '/BBB/,$d'

--
Chris F.A. Johnson, author <http://shell.cfajohnson,com/>
===================================================================
Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress)
Pro Bash Programming: Scripting the GNU/Linux Shell (2009, Apress)
===== My code in this post, if any, assumes the POSIX locale =====
===== and is released under the GNU General Public Licence =====

Janis Papanagnou

unread,
Nov 18, 2009, 6:25:19 PM11/18/09
to

Mind using awk?

awk '/BBB/{f=0};f;/AAA/{f=1}'


Janis

#! /shell/nerd

unread,
Nov 18, 2009, 6:31:32 PM11/18/09
to

Following is the output of sed command I used & not the file content -


AAA
some text
some text
BBB

The file contains so many other blocks too. So the command you gave
doesn't help. It would remove the first & last line from the file &
not from this filtered block. Correct me if I'm wrong.

#! /shell/nerd

unread,
Nov 18, 2009, 6:35:59 PM11/18/09
to
On Nov 18, 5:25 pm, Janis Papanagnou <janis_papanag...@hotmail.com>
wrote:

It works. Please explain it to me. I'm not so good with awk. Also I
find the Second regex is used first. Why is this order important.

pk

unread,
Nov 18, 2009, 6:36:46 PM11/18/09
to
#! /shell/nerd wrote:

> HI,
>
> sed '/AAA/,/BBB/p' <file> gives me
>
> AAA
> some text
> some text
> BBB

I don't think so.



> Now I want is the out put without AAA or BBB. How is this possible
> with a single sed command? I tried following but didn't work -
> sed '/AAA/,/BBB/{ 1d; $d; p; }' <file>

Just exclude the endpoints:

sed -n '/AAA/,/BBB/{
/AAA/b
/BBB/b
p
}'

Ed Morton

unread,
Nov 18, 2009, 7:29:07 PM11/18/09
to
#! /shell/nerd wrote:
> HI,
>
> sed '/AAA/,/BBB/p' <file> gives me
>
> AAA
> some text
> some text
> BBB
>
>
> Now I want is the out put without AAA or BBB. How is this possible
> with a single sed command?

Chances are it'll require an apparently random chain of single
characters in some arcane configuration. sed is an excellent tool for
simple substitutions on a single line. For anything else you should use
awk, perl, etc. In this case:

awk '/BBB/{f=0} f; /AAA/{f=1}' file

Ed.

Randal L. Schwartz

unread,
Nov 18, 2009, 8:23:28 PM11/18/09
to
>>>>> "#!" == #! /shell/nerd <vika...@gmail.com> writes:

#!> HI,
#!> sed '/AAA/,/BBB/p' <file> gives me

#!> AAA
#!> some text
#!> some text
#!> BBB

#!> Now I want is the out put without AAA or BBB. How is this possible
#!> with a single sed command? I tried following but didn't work -
#!> sed '/AAA/,/BBB/{ 1d; $d; p; }' <file>

If you don't mind a bit of Perl, Perl gives hints when
you're at the end of a range:

perl -ne 'my $in = /AAA/../BBB/; print if $in and $in > 1 and not $in =~ /E/'

Explanation: $in will go from 1 to n for each line within the matched range.
Clearly, we don't want to print line 1. But Perl also codes line 'n' with
"E0" appended, which doesn't affect its numeric value but can be detected with
a regex.

Slick.

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<mer...@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion

Ed Morton

unread,
Nov 18, 2009, 8:58:34 PM11/18/09
to

That would delete other lines within the selected range that
also just happened to match the start pattern:

$ cat file1
a
b
AAA
c
d
AAA
e
f
BBB
g
h

$ awk '/BBB/{f=0} f; /AAA/{f=1}' file1
c
d
AAA
e
f

$ sed -n '/AAA/,/BBB/{
/AAA/b
/BBB/b
p
}' file1
c
d
e
f


Regards,

Ed.

Janis Papanagnou

unread,
Nov 18, 2009, 9:04:08 PM11/18/09
to

More legible the awk expressions are written one on each line

/BBB/ {f=0}
f # here default action is: print $0 (i.e. whole line)
/AAA/ {f=1}

This is a state machine that operates with a flag variable f which
controls printing. For each input line the three awk expressions are
executed sequentially. If /BBB/ is found the flag to print is reset
to 0. The check for reset must come first, otherwise a line containing
/BBB/ would be printed (with the second awk statement) which is not
desired. Assume /AAA/ comes before the line containing f, then the
line containing /AAA/ would be printed which is also undesired.

Janis

Rakesh Sharma

unread,
Nov 19, 2009, 1:42:16 AM11/19/09
to

On some seds (e.g., GNU sed):
sed -e '/AAA/,/BBB/!d;//d' yourfile

But you can always do this too:
sed -e '/AAA/,/BBB/!d;/AAA/d;/BBB/d' yourfile

sed -ne '/AAA/,/BBB/{;/AAA/!{;/BBB/!p;};}' yourfile

Ed Morton

unread,
Nov 19, 2009, 4:00:12 AM11/19/09
to

The GNU one seems to work (though I don't understand why, but then I've only
been using sed for 25 years!), but the other 2 delete lines containing the start
pattern if they appear within the selected region:

$ cat file1
a
AAA
b
AAA
c
BBB
d
$ sed -e '/AAA/,/BBB/!d;//d' file1
b
AAA
c
$ sed -e '/AAA/,/BBB/!d;/AAA/d;/BBB/d' file1
b
c
$ sed -ne '/AAA/,/BBB/{;/AAA/!{;/BBB/!p;};}' file1
b
c

Regards,

Ed.

pk

unread,
Nov 19, 2009, 4:20:30 AM11/19/09
to
Ed Morton wrote:

>>> Now I want is the out put without AAA or BBB. How is this possible
>>> with a single sed command? I tried following but didn't work -
>>> sed '/AAA/,/BBB/{ 1d; $d; p; }' <file>
>>
>> Just exclude the endpoints:
>>
>> sed -n '/AAA/,/BBB/{
>> /AAA/b
>> /BBB/b
>> p
>> }'
>
> That would delete other lines within the selected range that
> also just happened to match the start pattern:

Well, I based my answer on the output he showed.
But what you say is true. It can still be done with sed, but it's probably
not worth the effort since cleaner solutions have been posted already.
Thanks for catching that.

Ed Morton

unread,
Nov 19, 2009, 5:18:17 AM11/19/09
to
pk wrote:
> Ed Morton wrote:
>
>>>> Now I want is the out put without AAA or BBB. How is this possible
>>>> with a single sed command? I tried following but didn't work -
>>>> sed '/AAA/,/BBB/{ 1d; $d; p; }' <file>
>>> Just exclude the endpoints:
>>>
>>> sed -n '/AAA/,/BBB/{
>>> /AAA/b
>>> /BBB/b
>>> p
>>> }'
>> That would delete other lines within the selected range that
>> also just happened to match the start pattern:
>
> Well, I based my answer on the output he showed.

Yeah, and that's always more challenging when the OP doesn't post any input!

Ed.

Rakesh Sharma

unread,
Nov 19, 2009, 1:56:26 PM11/19/09
to


sed -e '
/AAA/,/BBB/!d
/AAA/{
x;/./!d;x;b
}
/BBB/d
' yourfile

Michael Paoli

unread,
Nov 27, 2009, 10:48:08 PM11/27/09
to
On Nov 18, 3:14 pm, "#! /shell/nerd" <vika...@gmail.com> wrote:
> sed '/AAA/,/BBB/p' <file> gives me
> AAA
> some text
> some text
> BBB

Now, that would seem to be a rather interesting trick without the -n
option to sed(1), as the default action is p, and an explicit p would
then double that output, e.g.:

$ echo 'AAA
> some text
> some text
> BBB' |
> sed '/AAA/,/BBB/p'
AAA


AAA
some text
some text
some text
some text
BBB
BBB

> Now I want is the out put without AAA or BBB. How is this possible
> with a single sed command? I tried following but didn't work -
> sed '/AAA/,/BBB/{ 1d; $d; p; }' <file>

So, let's presume you meant something more like:
sed -ne '/AAA/,/BBB/p' <file>
gave you:


AAA
some text
some text
BBB

and want similar, but without the starting AAA and ending BBB lines.
sed -ne '/AAA/,/BBB/{;/AAA/n;:l;/BBB/d;p;n;bl;}'

w_a_x_man

unread,
Nov 27, 2009, 11:46:14 PM11/27/09
to

ruby -ne'BEGIN{$a=[]};$a << $_ if ~/AAA/ .. ~/BBB/;END{puts $a
[1..-2]}' file

0 new messages