Regex one-liner to find several multi-line blocks of text in a single file

2012-11-01 Thread Thomas Smith
Hi,

I'm trying to search a file for several matching blocks of text. A sample
of what I'm searching through is below.

What I want to do is match "# START block #" through to the next
"# END block #" and repeat that throughout the file without
matching any of the text that falls between each matched block (that is,
the "ok: some text" lines should not be matched). Here is the one-liner I'm
using:

perl -p -e '/^# START block #.*# END block #$/s' file.txt

I've tried a few variations of this but with the same result--a match is
being made from the first "# START block #" to the last "# END
block #", and everything in between... I believe that the ".*",
combined with the "s" modifier, in the regex is causing this match to be
made.

What I'm not sure how to do is tell Perl to search from START to the next
END and then start the search pattern over again with the next START-END
match.

How might I go about achieving this?

Thank you,

~ Tom

- Example Text -

# START block #
#

A block of text.

#
# END block #

ok: some text

# START block #
#

A block of text.

#
# END block #

ok: some text


Re: Regex one-liner to find several multi-line blocks of text in a single file

2012-11-01 Thread Paul Johnson
On Thu, Nov 01, 2012 at 12:44:08AM -0700, Thomas Smith wrote:
> Hi,
> 
> I'm trying to search a file for several matching blocks of text. A sample
> of what I'm searching through is below.
> 
> What I want to do is match "# START block #" through to the next
> "# END block #" and repeat that throughout the file without
> matching any of the text that falls between each matched block (that is,
> the "ok: some text" lines should not be matched). Here is the one-liner I'm
> using:
> 
> perl -p -e '/^# START block #.*# END block #$/s' file.txt
> 
> I've tried a few variations of this but with the same result--a match is
> being made from the first "# START block #" to the last "# END
> block #", and everything in between... I believe that the ".*",
> combined with the "s" modifier, in the regex is causing this match to be
> made.
> 
> What I'm not sure how to do is tell Perl to search from START to the next
> END and then start the search pattern over again with the next START-END
> match.
> 
> How might I go about achieving this?

perl -ne 'print if /# START block #/ .. /# END block #/' 
file.txt

-- 
Paul Johnson - p...@pjcj.net
http://www.pjcj.net

-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: Regex one-liner to find several multi-line blocks of text in a single file

2012-11-01 Thread Jim Gibson

On Nov 1, 2012, at 12:44 AM, Thomas Smith wrote:

> Hi,
> 
> I'm trying to search a file for several matching blocks of text. A sample
> of what I'm searching through is below.
> 
> What I want to do is match "# START block #" through to the next
> "# END block #" and repeat that throughout the file without
> matching any of the text that falls between each matched block (that is,
> the "ok: some text" lines should not be matched). Here is the one-liner I'm
> using:
> 
> perl -p -e '/^# START block #.*# END block #$/s' file.txt
> 
> I've tried a few variations of this but with the same result--a match is
> being made from the first "# START block #" to the last "# END
> block #", and everything in between... I believe that the ".*",
> combined with the "s" modifier, in the regex is causing this match to be
> made.

The '*' is what's called a "greedy" quantifier. That means it will match as 
many characters in the string as possible. What the regular expression engine 
does when it encounters the pattern '.*' is to immediately match it with as 
many characters as possible. Since your regular expression includes the 's' 
modifier, this will include newlines as well. When the RE engine sees that 
there are characters in the pattern after the '.*', it will start removing 
characters from the end of the substring matched by the '.*' until the 
subsequent pattern characters are also matched. This will continue until there 
are no characters matched by the '.*'.

The result of all this is that for your pattern, the last '# END block 
#' substring is the one that will be matched, and the '.*' pattern will 
match everything between the first '# START block #' and the last 
'# END block #'.

The way to fix this is to make the '*' quantifier "non-greedy" by putting a '?' 
quantifier after it. With that pattern, the RE engine will match as few 
characters as possible, and the first START block will pair up with the first 
subsequent END block. A 'g' modifier will tell the RE engine to start looking 
after each match for the next match in the string.



--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: my first useful program...any corrections/suggestions?

2012-11-01 Thread Thanos Zygouris
Thank you both for your suggestions.

@Shlomi: It seems that i'm completely unable to implement dispatch tables here
(but i now know what they are, hope to use them in the near future), so i used
the given-when approach...it seemed better than endless if-elsif's.

@Brandon: I'll stick with the m//, mostly because it reminds me that i can use
any delimiter instead of the slashes. I hope to get more experience tho, and
get rid of it. Also, i couldn't find any reference that \d in regex is
different from [0-9] (or [:digit:]), but i'm interested for more information
about it.

@both: Thanks again for looking into my code. You helped me learn a lot more
(and in less time) than try to figure them out myself. I tried to use most
of your suggestions...hope I've done it well enough.

So, here is the new code (i'm pretty happy with how it became):

#!/usr/bin/perl

use strict;
use warnings FATAL => qw( uninitialized );
use v5.16;

use X::Osd;
use IPC::Cmd qw( can_run run );

# check if amixer exists and get its path
my $amixer_path = can_run('amixer') 
or die 'amixer is not available';

# create osd bar (two output lines)
my $osd = X::Osd->new(2);
# osd bar properties
$osd->set_font("-*-terminus-bold-*-*-*-18-*-*-*-*-*-*-*");
$osd->set_shadow_offset(1);
$osd->set_pos(XOSD_bottom);
$osd->set_align(XOSD_center);
$osd->set_horizontal_offset(0);
$osd->set_vertical_offset(30);
$osd->set_timeout(5);

# locate (and if missing create) named pipe
my $fifo_file = $ENV{OSD_VOLUME} // "$ENV{HOME}/.osd-volume.fifo";
unless (-p $fifo_file) {
# if anyother filetype is there, just die
if (-e $fifo_file) {
die "$fifo_file: not a named pipe";
}
else {
# create the named pipe
require POSIX;
POSIX::mkfifo( $fifo_file, 0600 )
or die "cannot mkfifo $fifo_file: $!";
}
}

# open named pipe
open( my $fifo_fh, "+<", $fifo_file ) 
or die "cannot open $fifo_file: $!";

my $amixer_vol;

# constantly read from it
FIFO_INPUT:
while (chomp( my $fifo_input = <$fifo_fh> )) {
given ($fifo_input) {
when ('up') { $amixer_vol = '3%+'; }
when ('down')   { $amixer_vol = '3%-'; }
when ('toggle') { $amixer_vol = 'toggle'; }
when ('exit')   { last FIFO_INPUT; }
default {
warn "$fifo_input: invalid input";
next FIFO_INPUT;
}
}

# set new volume value and read the output
my $amixer_cmd = "$amixer_path sset Master,0 $amixer_vol";
my $amixer;
run(
command => $amixer_cmd,
verbose => 0,
buffer  => \$amixer,
);

# red output color if sound mutes, blue otherwise
my $colour = ( index($amixer, '[off]') != -1 ) ? '#DD' : '#1E90FF';
$osd->set_colour($colour);

# get new volume value and print osd bar
if (my ($volume) = $amixer =~ m/(\d{1,3})%/ ) {
$osd->string(0, "Master Volume:${volume}%");
$osd->percentage(1, $volume);
}
}

# close pipe before exit
close($fifo_fh);
exit(0);

-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: Is comp.lang.perl dead?

2012-11-01 Thread Rui Maciel
shawn wilson wrote:

> i thought usenet died in '96? i got a news reader up the other day,
> went through some feeds and haven't opened it sense.

It died just like a website dies when you stop visiting it.


Rui Maciel

-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/