Re: Finding part of a file
by davorg (Chancellor) on Dec 04, 2001 at 16:00 UTC
|
#!/usr/bin/perl -w
use strict;
my ($start, $end) = qw(banana grape);
while (<DATA>) {
if (/^$start$/ .. /^$end$/) {
print unless /^($start|$end)$/;
}
}
__END__
apple
banana
pear
peach
grape
orange
Update: Thanks to blakem for pointing out the
missing $ on the end of the flip-flop. He also
points out that this may be a good place to use the
/o option to the match operator and I agree. You
should probably benchmark to see how much of a gain you
get.
--
<http://www.dave.org.uk>
"The first rule of Perl club is you do not talk about
Perl club." -- Chip Salzenberg
| [reply] [Watch: Dir/Any] [d/l] |
|
I don't know if this is any better, but just for variety (using an extra variable, but shorter match pattern):
if (my $status = /^$start$/ .. /^$end$/) {
print unless $status =~ /^1$|E/;
}
# Or no extra variable, but getting more obfuscated :)
print if (/^$start$/../^$end$/) !~ /^1?$|E/;
| [reply] [Watch: Dir/Any] [d/l] |
|
Nifty... I didn't know that the flip flop returned anything other than 1 or 0.
% perl -lne 'printf "%-6s %s\n", $_, scalar(/^banana$/ .. /^grape$/)
+' fruit.txt
apple
banana 1
pear 2
peach 3
grape 4E0
orange
So, I can tweak my one-liner to exclude the endpoints like so:
% perl -ne 'print unless (/^banana$/ .. /^grape$/) =~ /^1?$|E/' fruit
+.txt
pear
peach
Update:
Doh!, runrigs second stanza was added while I was replying.... I guess obfuscated minds think alike. ;-)
-Blake
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Finding part of a file
by blakem (Monsignor) on Dec 04, 2001 at 15:43 UTC
|
This one-liner will get you most of the way there... though the endpoints (banana and grape) are included in the output as well...
% perl -ne 'print if /^banana$/ .. /^grape$/' fruit.txt
banana
pear
peach
grape
% cat fruit.txt
apple
banana
pear
peach
grape
orange
-Blake
| [reply] [Watch: Dir/Any] [d/l] |
|
Are we allowed to assume a unix box?
awk -e '/banana/,/grape/' fruit.txt
Its always a good idea to remember where these good ideas come from :-)
One side-effect of learning perl is that you become unable to write non-trivial awk, IME.
| [reply] [Watch: Dir/Any] |
|
I like sed:
sed -n '/banana/,/grape/p' fruit.txt
but find that almost anything I could do in sed, I would prefer to do in Perl. :-)
Impossible Robot
| [reply] [Watch: Dir/Any] |
Re: Finding part of a file
by broquaint (Abbot) on Dec 04, 2001 at 16:42 UTC
|
You could refer to good ol' regex if the flip-flop operator scares
use strict;
my ($start, $end) = ("bar".$/, $/."xxx");
my $data = join "", <DATA>;
my ($inbetween) = $data =~ /$start(.*?)$end/s;
print $inbetween, $/;
__DATA__
foo
bar
baz
quux
zab
xxx
foo
While not the most elegant of solutions (unless you're regex mad ;o) a little TMTOWTDI never hurt anyone, right?
HTH
broquaint | [reply] [Watch: Dir/Any] [d/l] |
|
my $begin = shift @ARGV;
my $end = shift @ARGV;
$_=<> until /^$begin$/;
while (<>) {
last if /^$end$/;
print;
}
This is what struck me as the most obvious solution, but, of course, there's more than one obvious way to do it... | [reply] [Watch: Dir/Any] [d/l] |
|
You can nest reads on an open filehandle. I didn't know
this until looking at your code and playing with it a little;
here's what I got.
#!/usr/bin/perl
$begin='banana';
$end='grape';
while(<DATA>) {
/$begin/ ? eval { /$end/ ? last : print while (<DATA>) }
: next
}
__DATA__
apple
banana
pear
peach
grape
prange
blyman | [reply] [Watch: Dir/Any] [d/l] |
|
|
Re: Finding part of a file
by mce (Curate) on Dec 04, 2001 at 15:49 UTC
|
use strict;
use warnings;
{
local $/="";
<DATA> =~ /banana\n(.*)\ngrape\n/s;
print $1;
}
__DATA__
apple
banana
pear
peach
grape
orange
The local is not needed in this case, but it is a good habit to use it since you are resetting perl internal
variables.
This prints
pear
peach
I hope this helps,
---------------------------
Dr. Mark Ceulemans
Senior Consultant
IT Masters, Belgium
| [reply] [Watch: Dir/Any] [d/l] |
|
At Mr. Ceulemans reply, I'd like to show up a different way, without the use of $1:
{
local $/ = undef;
my ($foundString) = ( <DATA> =~ /\bbanana\n(.*)\ngrape\n/s );
print $foundString;
}
__DATA__
apple
banana
pear
peach
grape
orange
The problem with this code might be multivalued lines (because of \b)...
Best regards,
Strat | [reply] [Watch: Dir/Any] [d/l] |
Re: Finding part of a file
by George_Sherston (Vicar) on Dec 04, 2001 at 15:31 UTC
|
update: changed chop to chomp on Aighearach's suggestion, which is of course very sensible, as one doesn't know for sure that the record separator will only be one character.
AFAIK you have to read through the file. You can only pull out a pre-determined fragment of the file if you know its location in bytes. Then you would use seek and read. But unless it's a huge file, there's no harm in doing something like
my $start = 'banana';
my $end = 'grape';
my $get = 0;
my @results;
open FILE, "file.txt";
while (<FILE>) {
chomp;
$get = 0 if $_ eq $end;
push @results, $_ if $get;
$get = 1 if $_ eq $start;
}
print $_,"\n" for @results;
You'd need something a little more subtle if you aren't sure that 'banana' comes before 'grape' or you think one or other might be absent altogether.
§ George Sherston | [reply] [Watch: Dir/Any] [d/l] [select] |
|
You might want to consider chomp instead of chop
-- Snazzy tagline here
| [reply] [Watch: Dir/Any] |
Re: Finding part of a file
by mkmcconn (Chaplain) on Dec 05, 2001 at 14:22 UTC
|
#!/usr/bin/perl -wl
# gate : a printer gate
use strict;
use Getopt::Std;
use constant OPEN => 1;
use constant SHUT => 0;
use vars qw($opt_p $opt_o $opt_s $opt_b $opt_l);
local ($opt_p, $opt_o, $opt_s, $opt_b, $opt_l);
getopts(qw(pb:o:s:l:));
unless ($opt_o or $opt_b ){
usage() unless $opt_p;
}
if (@ARGV){
open FH, $ARGV[0] or die $!;
} else {
*FH = \*DATA ;
}
my $enter = $opt_p ? $opt_p : SHUT; # breeze
my $breach = $opt_b ? $opt_b : 'the burgler breaks in';
my $open = $opt_o ? $opt_o : 'the butler opens the door';
my $shut = $opt_s ? $opt_s : 'the bouncer shuts the door';
my $last = $opt_l ? $opt_l : 'the bellhop is last through the door
+';
while (my $door = $_ = <FH>){
chomp ($door,$_);
exit if $door =~ /^$shut$/; # bouncer
$enter = OPEN if $door =~ /^$breach$/; # burgler
$enter and print;
$enter = OPEN if $door =~ /^$open$/; # butler
exit if $door =~ /^$last$/; # bellhop
}
sub usage
{
print "The door is shut\n",
"$0
-p (p_neuma is Greek for 'breeze')
-b (burgler b_reaks in) <item>
-o (butler o_pens the door) <item>
-s (bouncer s_huts the door) <item>
-l (bellhop is l_ast through the door)<item>
";
die"\n";
}
__END__
apple
banana
pear
peach
grape
orange
$ gate -o banana -s grape
pear
peach
update2
$ gate -o apex -s apple ./words
apexed
...
applausively
mkmcconn | [reply] [Watch: Dir/Any] [d/l] |