Re: Detect Two Strings in File
by GrandFather (Saint) on Nov 05, 2014 at 22:08 UTC
|
If you have two things to do, do them as two things. First find the first string, then as a second thing find the second string. Consider:
#!/usr/bin/perl
use strict;
use warnings;
my $str1 = 'through a file';
my $str2 = 'string';
my $lastStr2Line;
1 while <DATA> !~ m/$str1/;
m/$str2/ and $lastStr2Line = $. while $_ = <DATA>;
die "String 2 '$str2' not found\n" if ! defined $lastStr2Line;
print "String 2 last found on line $lastStr2Line\n";
__DATA__
Here's a good one. Looking to read through a file and then detect a ce
+rtain
string. Then check again sometime later to detect a different string a
+nd alert
if that different string isn't found. While this string could appear a
+nywhere in
the file, I would only want the last found string to run this check on
+...
example:
Prints:
String 2 last found on line 4
Perl is the programming world's equivalent of English
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
You are not looking for the last possible 'through a file' string! If this string happens a second time, after 'string' happened, your program gives a false positive.
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James My blog: Imperial Deltronics
| [reply] [Watch: Dir/Any] |
Re: Detect Two Strings in File
by CountZero (Bishop) on Nov 06, 2014 at 05:09 UTC
|
I think the following program takes care of the edge case too: when you have the first and second word in the right order and then the first word comes again and is not followed anymore by the second word. The OP made clear that he only had to look for the last occurrence of the first word. use Modern::Perl '2014';
my $first = qr/STRING/;
my $second = qr/MAGIC/;
my $first_pos;
my $second_pos;
while (<DATA>) {
$first_pos = $. if /$first/;
$second_pos = $. if /$second/;
}
if ( $first_pos and $second_pos > $first_pos ) {
say "Success! STRING at $first_pos followed by MAGIC at $second_po
+s";
}
else {
say "Failure! (STRING: $first_pos - MAGIC: $second_pos)";
}
__DATA__
First line
second line
here is the STRING
empty text
the STRING again!
followed by the MAGIC word
more emptiness
Oh no! the first STRING again
sadness
did we look in vain?
Ah, MAGIC success
To test the edge case, delete the last line of the DATA-section.I have assumed that the first and second words cannot happen in the same line.
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James My blog: Imperial Deltronics
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Sorry to clarify, they absolutely can appear on the same line or may appear on a newline. The only conditions set forth is only the LAST found "string1" needs to be detected. Then from that point foward, find "string2", ignoring everything prior to "string1". If "string2" is not found ON ANY LINE (same or new), yell something.
Let me test through a few scenarios and see if I can clarify further.
After testing your solution here this does indeed seem to be on the right track. It grabbed the last string1 found and then alerted when it found string2. Oddly enough string2 was found on two different lines, but it detected it on the 2nd line, not the first found.
Testing to see if it can be tailored to also detect if on same line
UPDATE - Looks like we can add this condition if it appears on the same line by adding this condition in the failure part:
if ($first_pos == $second_pos)
{
print "Success! (STRING: $first_pos matches same line as MAGIC : $
+second_pos)";
}
So this SHOULD work. Thanks again for the assistance | [reply] [Watch: Dir/Any] [d/l] |
|
use Modern::Perl '2014';
my $first = qr/STRING/;
my $second = qr/MAGIC/;
my $first_pos;
my $first_sub_pos;
my $second_pos;
my $second_sub_pos;
while (<DATA>) {
do { $first_pos = $.; $first_sub_pos = $-[0] } if /$first/;
do { $second_pos = $.; $second_sub_pos = $-[0] } if /$second/;
}
if ( $first_pos and $second_pos > $first_pos ) {
say "Success! STRING at $first_pos followed by MAGIC at $second_po
+s";
}
elsif ( $first_pos
and $second_pos == $first_pos
and $second_sub_pos > $first_sub_pos )
{
say
"Success! STRING (char: $first_sub_pos) followed by MAGIC (char: $seco
+nd_sub_pos) at $first_pos";
}
else {
say
"Failure! (STRING: $first_pos / $first_sub_pos - MAGIC: $second_pos /
+$second_sub_pos)";
}
__DATA__
First line
second line
here is the STRING
empty text
the STRING again!
followed by the MAGIC word
more emptiness
Oh no! the first STRING again
sadness
did we look in vain?
Ah, STRING and MAGIC success
MAGIC and STRING failed
Just add and delete the last lines of the DATA section to see the various possibilities.
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James My blog: Imperial Deltronics
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Detect Two Strings in File
by GotToBTru (Prior) on Nov 05, 2014 at 22:05 UTC
|
use strict;
use warnings;
my $file = 'testpm.dat';
my $string1 = 'open';
my $string2 = 'close';
open F, $file;
while (<F>) {
# if only there was a way to find one string within another!
}
close F;
if (I found string1 && I did not find string2) {
print "Alarm!\n";
}
| [reply] [Watch: Dir/Any] [d/l] |
Re: Detect Two Strings in File
by Loops (Curate) on Nov 05, 2014 at 21:48 UTC
|
my $str1 = qr(C);
my $str2 = qr(X);
my $alert = 0;
while (<DATA>) {
$alert = 1 if /$str1/;
$alert = 0 if /$str2/;
}
print "P A N I C" if $alert;
__DATA__
A
B
C
D
E
F
| [reply] [Watch: Dir/Any] [d/l] |
|
The OP didn't specify what to do if the first string isn't found. If it's not ok, set $alert to 1 before entering the loop.
| [reply] [Watch: Dir/Any] |
|
Your program will not alert in case it finds the second string but never found the first string. The OP indeed did not state clearly what he wants in that case, but whatever he wants, your program cannot distinguish that case.
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James My blog: Imperial Deltronics
| [reply] [Watch: Dir/Any] |
Re: Detect Two Strings in File
by boftx (Deacon) on Nov 05, 2014 at 23:33 UTC
|
What about the case where $str1 is never found? The solutions so far presented seem to ignore that case and the results appear to be indistinguishable from first finding $str1 and then $str2.
You must always remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
| [reply] [Watch: Dir/Any] |
Re: Detect Two Strings in File
by CountZero (Bishop) on Nov 07, 2014 at 05:41 UTC
|
No loops and just one regular expressioon: use Modern::Perl '2014';
my $first = qr/STRING/;
my $second = qr/MAGIC/;
my $corpus = join '', map { chomp; $_ } <DATA>;
if ( $corpus =~ m/($first)(?!.*$first).*($second)(?!.*$first)/ ) {
say "Success: $-[1] and $-[2]";
}
else {
say "Failure";
}
__DATA__
First line
second line
here is the STRING
empty text
the STRING again!
followed by the MAGIC word
more emptiness
Oh no! the first STRING again
sadness
did we look in vain?
Yes, It's like MAGIC
we are happy
Ah, STRING and MAGIC success
MAGIC and STRING failed
Fiddle around with the DATA-section to check the various possibilities and combiinations.
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James My blog: Imperial Deltronics
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] |