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>
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 =====
Mind using awk?
awk '/BBB/{f=0};f;/AAA/{f=1}'
Janis
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.
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.
> 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
}'
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.
#!> 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
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.
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
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
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.
>>> 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.
Yeah, and that's always more challenging when the OP doesn't post any input!
Ed.
sed -e '
/AAA/,/BBB/!d
/AAA/{
x;/./!d;x;b
}
/BBB/d
' yourfile
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;}'
ruby -ne'BEGIN{$a=[]};$a << $_ if ~/AAA/ .. ~/BBB/;END{puts $a
[1..-2]}' file