CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
Searching for a string

 



mohan
User

Jan 27, 2015, 2:17 AM

Post #1 of 51 (13720 views)
Searching for a string Can't Post

Hi Guys,

Need some help with the below Code :

Scenario :
I want to read a file and search for the keyword "font-size" used in it. If this is present then the CMD says "Font-size is found". The problem I'm now facing is when I use the below code, it reads all the lines and displayed the O/P many times. I want the O/P to come only once. If the font size is found anywhere in the file then it should come only once. And also this keyword font-size should not be considered it it's specified in "%" example font-size=100%.

Can someone help me with this?
Code :
#!/usr/bin/perl

$file = 'style.css';
open(txt, $file);
while($line = <txt>) {

if ($line =~ /font-size/) {
print "\n Forced Font is found \n";
}
}
close(txt);


Tejas
User

Jan 27, 2015, 3:32 AM

Post #2 of 51 (13718 views)
Re: [mohan] Searching for a string [In reply to] Can't Post


Code
#!/usr/bin/perl 

$file = 'style.csv';
#my $regex = qr/
# (?=.*font-size) &&
# (?!.*%)
# /ix;
open(txt, $file);
while($line = <txt>) {

if ($line =~ /font-size/) {
if($line !~ /%/){
print "Forced Font is found ,$line\n";
}
else {
print "Line has % in it , $line \n"
}
}
}
close(txt);


Please do not worry about the regex in the code.i tried to match the regex in the if condition first

Code
if  ($line =~ /$regex/)


it does work but it wont print any line with % in it, which i dont think is ur requirement

Thanks
Tejas


(This post was edited by Tejas on Jan 27, 2015, 3:32 AM)


BillKSmith
Veteran

Jan 27, 2015, 5:38 AM

Post #3 of 51 (13712 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

It is not necessary to read all the lines. Exit the loop right after you find and print the first match. Use last; after the print.


Code
if ($line =~ /font-size/) {  
print "\n Forced Font is found \n";
last;
}

Good Luck,
Bill


mohan
User

Jan 27, 2015, 7:42 PM

Post #4 of 51 (13702 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post

@Tejas,

This works perfectly fine as per my need !! Thanks a ton !

But there is a little modification to be done.

1. If the "font-size" is used 20 times the CMD displays it 20 times...I don't want this to happen..I just need the count of how many time it is used.

2. Also we use "$file = 'style.css';" to specify the file name here. Is it possible to read any CSS file in the current directoy without the need to specify the file name ?


Tejas
User

Jan 27, 2015, 8:49 PM

Post #5 of 51 (13700 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

i dint really get this.u mean, its printing 20 times per line ?
Can u please elaborate ?

Quote
1. If the "font-size" is used 20 times the CMD displays it 20 times...I don't want this to happen..I just need the count of how many time it is used.


Yes, u can send the file name as parameter , something like below

Code
./myfile.pl <filename>


Code



      
    


mohan
User

Jan 27, 2015, 10:21 PM

Post #6 of 51 (13697 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post

If the CSS file has "font-size" specified 20 times in different lines, then the CMD prints the same 20 times..But i dont want this to happen...The CMD should just say "font-size found in 20 instances"


mohan
User

Jan 27, 2015, 10:23 PM

Post #7 of 51 (13696 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post

And for this :


Yes, u can send the file name as parameter , something like below
Code

./myfile.pl <filename>
-------------------------------------------

I'm actually planning to convert this pl file into an exe file so that when you just run the exe file, the program should detect all the CSS file in that present directory and throws the O/P..So is there a possible way to do this?


(This post was edited by mohan on Jan 27, 2015, 10:32 PM)


Tejas
User

Jan 27, 2015, 10:45 PM

Post #8 of 51 (13688 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

Yes, it is possible.
Please follow Chris's post .

http://perlguru.com/gforum.cgi?post=79347;search_string=read%20files%20from%20a%20directory;#79347

You can do something like this


Code
use strict; 
use warnings;
my @files;
opendir(Dir, $Directoryname) or die "cannot open directory $Directoryname";
@files = grep(/\.txt$/,readdir(Dir));


All your filenames would a part of array @files.

to access them



Code
foreach $file (@files) { 
open my $handle, '<', $file or die "could not open '$file': $!";
while (my $line = <$handle>) {
#Your checks per line

}

}


The code pasted above is untested and probably would work as per ur requirements

Thanks
Tejas


(This post was edited by Tejas on Jan 27, 2015, 11:45 PM)


mohan
User

Jan 27, 2015, 11:55 PM

Post #9 of 51 (13683 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post

I just tried the above code and merged it together as . Please bear with me since i'm trying to learn perl : (The directory to be read is "bin" )

#!/usr/bin/perl

my @files;
opendir(bin, $Directoryname) or die "cannot open directory $Directoryname";
@files = grep(/\.css$/,readdir(bin));
#my $regex = qr/
# (?=.*font-size) &&
# (?!.*%)
# /ix;
foreach $file (@files) {
open my $handle, '<', $file or die "could not open '$file': $!";
while (my $line = <$handle>) {

if ($line =~ /font-size/) {
if($line !~ /%/){
print "\n Forced Font is detected. -- $line\n";
}
else {
print "\n Font is specified in % -- $line \n"
}
}

if ($line =~ /line-height/) {

print "\n Forced Line-height is detected. \n";
}


if ($line =~ /position:absolute/) {

print "\n position:absolute is detected. \n";

}
}

}
close(txt);

This is giving the O/P as :

cannot open directory at C:\Perl64\bin\sample1.pl line 4.


Tejas
User

Jan 28, 2015, 12:26 AM

Post #10 of 51 (13678 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

You have specified the wrong parameter as directory name in opendir
Also, please read about opendir func in perl docs

And u can specify all the patterns u want in an array , so that u wouldnt need so many if conditions in the code, which will end up confusing you
something like below and loop through the array


Code
  
my @patterns = ('font-size','line-height','position:absolute');


if u dint understand it properly,below is the way you have tried
Below should work.

Code
my @files;  

my $Directoryname = '/bin';
opendir(bin, $Directoryname) or die "cannot open directory $Directoryname";
@files = grep(/\.css$/,readdir(bin));

foreach $file (@files) {
open my $handle, '<', $file or die "could not open '$file': $!";
while (my $line = <$handle>) {

if ($line =~ /font-size/) {
if($line !~ /%/){
print "\n Forced Font is detected. -- $line\n";
}
else {
print "\n Font is specified in % -- $line \n"
}
}

if ($line =~ /line-height/) {
print "\n Forced Line-height is detected. \n";
}


if ($line =~ /position:absolute/) {
print "\n position:absolute is detected. \n";
}

}

}
close(txt);



mohan
User

Jan 28, 2015, 12:53 AM

Post #11 of 51 (13674 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post

I tried the above code and still getting the same error :

C:\Perl64\bin>sample1.pl
cannot open directory /bin at C:\Perl64\bin\sample1.pl line 4.


Tejas
User

Jan 28, 2015, 1:11 AM

Post #12 of 51 (13664 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

try to change the variable to your present working diectory

my $Directoryname = "your directory" ;


mohan
User

Jan 28, 2015, 1:14 AM

Post #13 of 51 (13662 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post

Actually "bin" is the current working directory..and it's not working :(


mohan
User

Jan 28, 2015, 1:19 AM

Post #14 of 51 (13658 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post

But when i use "my $Directoryname = getcwd ; " the code is working....does this mean when i convert the code into exe and place that exe in a current folder and run, it will execute without any errors?


Tejas
User

Jan 28, 2015, 1:25 AM

Post #15 of 51 (13656 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

OK
Just try the code below
and try to se whats it is doing first


Code
use strict; 
use warinings;

use Cwd;

my $Directoryname = getcwd();

print "My Current Dir is $Directoryname \n";
my @files;

opendir(bin, $Directoryname) or die "cannot open directory $Directoryname";
@files = map { "$Directoryname/$_" } grep(/\.css$/,readdir(bin));.

foreach $file (@files) {
open my $handle, '<', $file or die "could not open '$file': $!";
while (my $line = <$handle>) {

if ($line =~ /font-size/) {
if($line !~ /%/){
print "\n Forced Font is detected. -- $line\n";
}
else {
print "\n Font is specified in % -- $line \n"
}
}

if ($line =~ /line-height/) {
print "\n Forced Line-height is detected. \n";
}


if ($line =~ /position:absolute/) {
print "\n position:absolute is detected. \n";
}

}
close($handle);
}


I will explain it later.
But you try to see what the code is doing

Thanks
Tejas


mohan
User

Jan 28, 2015, 1:29 AM

Post #16 of 51 (13652 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post

Just got this error when i ran the code :

C:\Perl64\bin>sample1.pl
Can't locate warinings.pm in @INC (@INC contains: C:/Perl64/site/lib C:/Perl64/l
ib .) at C:\Perl64\bin\sample1.pl line 2.
BEGIN failed--compilation aborted at C:\Perl64\bin\sample1.pl line 2.

What does this mean?


Tejas
User

Jan 28, 2015, 1:37 AM

Post #17 of 51 (13647 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

use warnings;

at the top
its a typo


mohan
User

Jan 28, 2015, 2:12 AM

Post #18 of 51 (13639 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post

got the below errors :

C:\Perl64\bin>sample1.pl
Unquoted string "bin" may clash with future reserved word at C:\Perl64\bin\sampl
e1.pl line 11.
Unquoted string "bin" may clash with future reserved word at C:\Perl64\bin\sampl
e1.pl line 12.
syntax error at C:\Perl64\bin\sample1.pl line 12, near ";."
Global symbol "$file" requires explicit package name at C:\Perl64\bin\sample1.pl
line 14.
Global symbol "$handle" requires explicit package name at C:\Perl64\bin\sample1.
pl line 16.
syntax error at C:\Perl64\bin\sample1.pl line 38, near "}"
Execution of C:\Perl64\bin\sample1.pl aborted due to compilation errors.


Tejas
User

Jan 28, 2015, 2:58 AM

Post #19 of 51 (13612 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

Dude, try to change the code to your requirements and do not run it blindly
as i have not tested it on my box.

i will try and look into it
Thankss
Tejas


Tejas
User

Jan 28, 2015, 3:00 AM

Post #20 of 51 (13610 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

@files = map { "$Directoryname/$_" } grep(/\.css$/,readdir(bin));
change this to what ever worked for u for time being.


Tejas
User

Jan 28, 2015, 5:03 AM

Post #21 of 51 (13561 views)
Re: [mohan] Searching for a string [In reply to] Can't Post


Code
use strict;  
use warnings;

use Cwd;

my $Directoryname = getcwd();

print "My Current Dir is $Directoryname \n";

my @files;

opendir(mydir, $Directoryname) or die "cannot open directory $Directoryname";
@files = map { "$Directoryname/$_" } grep(/\.css$/,readdir(mydir));

foreach my $file (@files) {
open my $handle, '<', $file or die "could not open '$file': $!";
while (my $line = <$handle>) {

if ($line =~ /font-size/) {
if($line !~ /%/){
print "\n Forced Font is detected. -- $line\n";
}
else {
print "\n Font is specified in % -- $line \n"
}
}

if ($line =~ /line-height/) {
print "\n Forced Line-height is detected. \n";
}


if ($line =~ /position:absolute/) {
print "\n position:absolute is detected. \n";
}

}
close($handle);
}

Try Testing above..its the same but removing an extra .


(This post was edited by Tejas on Jan 28, 2015, 5:40 AM)


Laurent_R
Veteran / Moderator

Jan 28, 2015, 10:05 AM

Post #22 of 51 (13545 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post

You should rather use a lexical dirhandle (just as you used a lexical filehandle). Also the glob function makes it easier to retrieve the file names:


Code
use strict;   
use warnings;
use Cwd;

my $dir = getcwd();
my @files = glob("$dir/*.css");
for my $file (@files) {
# ...
}


The additional good thing about glob it that you get the file names with their (relative) path, whereas readdir does not (it is not a problem here since your a reading in the default directory, but it is often quite useful to get the path).

Since you are reaading from thee default directory, the above code could be further simplified as follows:

Code
use strict;   
use warnings;

my @files = glob("*.css");
for my $file (@files) {
# ...
}


Or, simplifying another step further (untested, but should work):

Code
use strict;   
use warnings;

for my $file (glob("*.css")) {
# ...
}



Tejas
User

Jan 28, 2015, 10:38 AM

Post #23 of 51 (13543 views)
Re: [Laurent_R] Searching for a string [In reply to] Can't Post

Hi
I have used lexical dir handle
Can u please tell me where is the issue
Or am I confused about what a lexical dir handle is
Thanks
Tejas


FishMonger
Veteran / Moderator

Jan 28, 2015, 11:25 AM

Post #24 of 51 (13541 views)
Re: [Laurent_R] Searching for a string [In reply to] Can't Post


Code
for my $file (glob("*.css")) {


That could be further simplified to this:

Code
for my $file (<*.css>) {



mohan
User

Jan 28, 2015, 11:51 PM

Post #25 of 51 (13534 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post

Already tried removing the extra ".". Still shows the same error .


Tejas
User

Jan 28, 2015, 11:56 PM

Post #26 of 51 (9325 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

Can u please post your code and error


mohan
User

Jan 29, 2015, 12:53 AM

Post #27 of 51 (9323 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post

Actually the above code works !

but throws few errors :

Unquoted string "mydir" may clash with future reserved word at C:\Perl64\bin\sam
ple1.pl line 12.
Unquoted string "mydir" may clash with future reserved word at C:\Perl64\bin\sam
ple1.pl line 13.

Adding the code :

use strict;
use warnings;

use Cwd;

my $Directoryname = getcwd();

print "My Current Dir is $Directoryname \n";

my @files;

opendir(mydir, $Directoryname) or die "cannot open directory $Directoryname";
@files = map { "$Directoryname/$_" } grep(/\.css$/,readdir(mydir));

foreach my $file (@files) {
open my $handle, '<', $file or die "could not open '$file': $!";
while (my $line = <$handle>) {

if ($line =~ /font-size/) {
if($line !~ /%/){
print "\n Forced Font is detected. -- $line\n";
}
else {
print "\n Font is specified in % -- $line \n"
}
}

if ($line =~ /line-height/) {
print "\n Forced Line-height is detected. \n";
}


if ($line =~ /position:absolute/) {
print "\n position:absolute is detected. \n";
}

}
close($handle);
}


(This post was edited by mohan on Jan 29, 2015, 12:54 AM)


Tejas
User

Jan 29, 2015, 1:04 AM

Post #28 of 51 (9316 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

They are warnings but not errors
Try to apply Laurent or fishmongers recommendations for reading files in directory using glob

That is the more efficient way of accessing the files from a directory than the code I be posted

I would want u to remove the map that Iam using and change it to the way Laurent and fishmonger wanted .
And please post the updated code
If u find trouble in changing please ask

Use this


Code
for my $file (<*.css>) {


Instead of our for loop or try using glob

Thanks


(This post was edited by Tejas on Jan 29, 2015, 1:07 AM)


mohan
User

Jan 29, 2015, 1:13 AM

Post #29 of 51 (9310 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post

used laurent's suggestion and there was no warning seen and the O/P was correct.

Code :

use strict;
use warnings;

use Cwd;


my $dir = getcwd();
my @files = glob("$dir/*.css");

for my $file (@files) {
open my $handle, '<', $file or die "could not open '$file': $!";
while (my $line = <$handle>) {

if ($line =~ /font-size/) {
if($line !~ /%/){
print "\n Forced Font is detected. -- $line\n";
}
else {
print "\n Font is specified in % -- $line \n"
}
}

if ($line =~ /line-height/) {
print "\n Forced Line-height is detected. \n";
}


if ($line =~ /position:absolute/) {
print "\n position:absolute is detected. \n";
}

}
close($handle);
}


Tejas
User

Jan 29, 2015, 1:15 AM

Post #30 of 51 (9304 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

Sure,u can also try the below too
for my $file (<*.css>)


And I thought u wanted to end the loop if you see these patterns once
Is it not the case
Because with this code I'll keep looping till the end of file

Thanks
Tejas


mohan
User

Jan 29, 2015, 1:19 AM

Post #31 of 51 (9303 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post

Yes pls ! ..I don't want it to keep on running and flood the cmd and also wanna throw a message if there is no CSS files found in the cwd .


Zhris
Enthusiast

Jan 29, 2015, 8:39 AM

Post #32 of 51 (9276 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

Hi,

I see you have already received plenty of help with your problem, but wanted to provide the approach I would take. My version uses an operations array, where each element is a hash made up of a label ( in order to identity the test ), a test ( a code ref which accepts the line as an argument and returns either true or false indicating if the test passed or failed ), and a count ( dynamically added to the hash or reset while iterating over each file and incremented each time a test passes ). I find this approach more manageable than a group of conditions with individual count variables.


Code
use strict; 
use warnings;
use Cwd;

my @operations =
(
{
label => 'non percentile font size',
test => sub { $_[0] =~ /font-size\s*(:|=)\s*[^%]+$/ },
},
{
label => 'line height',
test => sub { $_[0] =~ /line-height/ },
},
{
label => 'position absolute',
test => sub { $_[0] =~ /position\s*(:|=)\s*absolute/ },
},
);

my $dirpath = getcwd;

my @filepaths = glob( "$dirpath/*.css" );

print "no css files\n" unless @filepaths;

for my $filepath ( @filepaths )
{
print "\n>>> $filepath <<<\n";

$_->{count} = 0 for ( @operations ); # set or reset counts.

open my $filehandle, '<', $filepath or die "could not open '$filepath': $!";

while ( my $line = <$filehandle> )
{
$_->{test}->( $line ) and $_->{count}++ for ( @operations ); # for each operation, call the test and increment count if it returns true.
}

close $filehandle;

print "$_->{label} occurred $_->{count} times\n" for ( @operations ); # for each operation, print the outcome.
}


Regards,

Chris


(This post was edited by Zhris on Jan 30, 2015, 6:56 AM)


Laurent_R
Veteran / Moderator

Jan 29, 2015, 11:01 AM

Post #33 of 51 (9222 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post


In Reply To
Hi
I have used lexical dir handle
Can u please tell me where is the issue
Or am I confused about what a lexical dir handle is


Here:

Code
opendir(mydir, $Directoryname) or die "cannot open directory $Directoryname";

"mydir" is a bareword dir handle. It is better to use something like this:

Code
opendir(my $dir, $Directoryname) or die "cannot open directory $Directoryname";

and the use $dir for reading the directory.


mohan
User

Jan 29, 2015, 9:59 PM

Post #34 of 51 (9183 views)
Re: [Zhris] Searching for a string [In reply to] Can't Post

I just tried this code and it's just awesome !! But when I convert it into .exe file using perlApp and run it, I can just see the cmd flashing for a microsecond and disappearing..is it possible to make the cmd stay unless we select the "ESC" key? (NOTE: I tried using the print screen and captured it..the file is running correctly just the cmd is closing out in less than a second)


(This post was edited by mohan on Jan 29, 2015, 10:01 PM)


mohan
User

Jan 29, 2015, 10:11 PM

Post #35 of 51 (9180 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

Added this and it works fine now :)

END {
print "Press enter to exit\n";
<>;
}


mohan
User

Jan 30, 2015, 2:53 AM

Post #36 of 51 (9166 views)
Re: [Zhris] Searching for a string [In reply to] Can't Post

Can you please help with one more thing here ?

The code posted below :


Code
use strict;  
use warnings;
use Cwd;

my @operations =
(
{
label => 'Harcoded font size value !!',
test => sub { $_[0] =~ /font-size\s*(:|=)\s*[^%]+$/ },
},
{
label => 'Forced Line height value !!',
test => sub { $_[0] =~ /line-height/ },
},
{
label => 'position absolute !!',
test => sub { $_[0] =~ /position\s*(:|=)\s*absolute/ },
},

{
label => 'Forced font color found !!',
test => sub { $_[0] =~ /color/ },
},
);

my $dirpath = getcwd;

my @filepaths = glob( "$dirpath/*.css" );

print "no css files\n" unless @filepaths;

for my $filepath ( @filepaths )
{
print "\n>>> $filepath <<<\n";

$_->{count} = 0 for ( @operations ); # set or reset counts.

open my $filehandle, '<', $filepath or die "could not open '$filepath': $!";

while ( my $line = <$filehandle> )
{
$_->{test}->( $line ) and $_->{count}++ for ( @operations ); # for each operation, call the test and increment count if it returns true.
}

close $filehandle;

print "$_->{label} $_->{count} Instance found\n" for ( @operations ); # for each operation, print the outcome.
}
END {
print "Press enter to exit\n";
<>;
}


Searches for all CSS files.

I need similar patter for files with "opf" extension as well...Can I just copy paste the same code ? Also, I need to use specific conditions when the search is carried out for "opf" files. They are:

1. Search for "language" keyword. If found print that line.
2. Search for "layout-get" and "fixed-get". If either of this is found then print "get" is found or if none of this is found then "print no get is found".

I don't need the "instance" count here since the "opf" file won't have the same keywords repeated many times


Zhris
Enthusiast

Jan 30, 2015, 6:55 AM

Post #37 of 51 (9151 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

Hi,


Quote
Can I just copy paste the same code


Do your new requirements need to be combined into the same script, or are two separate scripts desirable?

Chris


mohan
User

Jan 30, 2015, 7:41 AM

Post #38 of 51 (9143 views)
Re: [Zhris] Searching for a string [In reply to] Can't Post

Combining it in the same script would be great !


Zhris
Enthusiast

Jan 30, 2015, 9:31 AM

Post #39 of 51 (9129 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

Hi,

Upon combining, the script becomes quite complex due to the significant variations between each file type and/or each operation. Personally at this stage I might consider repeating sections of code or rewriting object orientatedly with file type specific classes and to some extent operation specific classes. Nonetheless, lets continue with a "definitions" data structure.

Firstly, I haven't supported short circuiting, in other words, for opf files once all operations have been achieved there is no point in reading the rest of the file. There are numerous ways this could be implemented if desired, which I'll leave to you. For now i.e. for language, the last line found is the one printed, although you mentioned there are no duplicates anyway.

The operations array has been replaced with a filedefs array. Each element is a hash which describes how to handle each file type. The action to be performed before processing the file, if a test passes and after processing the file, are now coderefs under preaction, testaction and postaction respectively. If you need an operation specific action, you can override by putting the action under a specific operation i.e. layout or fixed get postaction.


Code
use strict; 
use warnings;
use Cwd;

my @filedefs =
(
{
extension => 'css',
operations =>
[
{
label => 'Harcoded font size value',
test => sub { $_[1] =~ /font-size\s*(:|=)\s*[^%]+$/ },
},
{
label => 'Forced Line height value',
test => sub { $_[1] =~ /line-height/ },
},
{
label => 'position absolute',
test => sub { $_[1] =~ /position\s*(:|=)\s*absolute/ },
},
{
label => 'Forced font color',
test => sub { $_[1] =~ /^\s*color\s*(:|=)/ },
},
],
preaction => sub { $_[0]->{count} = 0 },
testaction => sub { $_[0]->{count}++ },
postaction => sub { print "$_[0]->{label} !! $_[0]->{count} Instance found\n" },
},
{
extension => 'opf',
operations =>
[
{
label => 'language',
test => sub { $_[1] =~ /language/ },
},
{
label => 'layout or fixed get',
test => sub { $_[1] =~ /(layout|fixed)-get/ },
postaction => sub { print +( defined $_[0]->{line} ) ? 'get is found' : 'no get is found', "\n" }
},
],
preaction => sub { $_[0]->{line} = undef },
testaction => sub { $_[0]->{line} = $_[1] },
postaction => sub { print $_[0]->{line} if defined $_[0]->{line} },
#shortcircuit => 1,
}
);

my $dirpath = getcwd;

for my $filedef ( @filedefs )
{
my @filepaths = glob( "$dirpath/*.$filedef->{extension}" );

print "\nno $filedef->{extension} files\n" unless @filepaths;

for my $filepath ( @filepaths )
{
print "\n>>> $filepath <<<\n";

for my $operation ( @{$filedef->{operations}} )
{
my $preaction = $operation->{preaction} // $filedef->{preaction};

$preaction->( $operation );
}

open my $filehandle, '<', $filepath or die "could not open '$filepath': $!";

while ( my $line = <$filehandle> )
{
for my $operation ( @{$filedef->{operations}} )
{
my $test = $operation->{test};
my $testaction = $operation->{testaction} // $filedef->{testaction};

$test->( $operation, $line ) and $testaction->( $operation, $line );
}
}

close $filehandle;

for my $operation ( @{$filedef->{operations}} )
{
my $postaction = $operation->{postaction} // $filedef->{postaction};

$postaction->( $operation );
}
}
}

END
{
print "\nPress enter to exit\n";
<>;
}


Regards,

Chris


(This post was edited by Zhris on Jan 30, 2015, 9:57 AM)


mohan
User

Feb 2, 2015, 1:14 AM

Post #40 of 51 (8980 views)
Re: [Zhris] Searching for a string [In reply to] Can't Post

Whoooooohhh !! That's one hell of a code there !! I wish I could use some of your brainCool

This code works absolutely fine, but I need some little modification to be done in the keywords !! sorry for that :

1. Search for "language" keyword. If found print that line. (Here the "language" keyword can be repeated multiple times and I want all the instance to be printed)
2. Search for "layout-get" and "fixed-get". If either of this is found then print "get" is found or if none of this is found then "print no get is found". (Instead of "layout-get" and "fixed-get" the keywords are "pre-paginated" and "name="fixed-layout" content="true""


Zhris
Enthusiast

Feb 2, 2015, 6:12 PM

Post #41 of 51 (8959 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

Hi,

After I last posted, I modified the code slightly to support short circuiting ( via operation attribute "done" ), chomping the line ( in case printing last line which doesn't have newline ) and have compacted a few of the blocks into a single line ( personal preference ). I will use this version instead, although its a little less readable. Fundamentally, in order to support your requirement adjustments, I modified the @filedefs array so that each of the opf operations have their own set of action coderefs that do the desirable thing accordingly.


Code
use strict; 
use warnings;
use Cwd;

my @filedefs =
(
{
extension => 'css',
preaction => sub { $_[0]->{count} = 0 },
testaction => sub { $_[0]->{count}++ },
postaction => sub { print "$_[0]->{label} !! $_[0]->{count} Instance found\n" },
operations =>
[
{
label => 'Harcoded font size value',
test => sub { $_[0] =~ /font-size\s*(:|=)\s*[^%]+$/ },
},
{
label => 'Forced Line height value',
test => sub { $_[0] =~ /line-height/ },
},
{
label => 'position absolute',
test => sub { $_[0] =~ /position\s*(:|=)\s*absolute/ },
},
{
label => 'Forced font color',
test => sub { $_[0] =~ /^\s*color\s*(:|=)/ },
},
],
},
{
extension => 'opf',
operations =>
[
{
label => 'language',
test => sub { $_[0] =~ /language/ },
testaction => sub { print "$_[1]\n" },
},
{
label => 'layout or fixed get',
test => sub { $_[0] =~ /(pre-paginated|\Qname="fixed-layout" content="true"\E)/ },
testaction => sub { $_[0]->{done} = 1 },
postaction => sub { print +( $_[0]->{done} ) ? 'get is found' : 'no get is found', "\n" },
},
],
}
);

my $dirpath = getcwd;

for my $filedef ( @filedefs )
{
my @filepaths = glob( "$dirpath/*.$filedef->{extension}" );

print "\nno $filedef->{extension} files\n" unless @filepaths;

for my $filepath ( @filepaths )
{
print "\n>>> $filepath <<<\n";

do { $_->{done} = 0; $_->{preaction} // $filedef->{preaction} // sub { } }->( $_ ) for ( @{$filedef->{operations}} );

open my $filehandle, '<', $filepath or die "could not open '$filepath': $!";

while ( my $line = <$filehandle> )
{
# note the below two lines could be handled more efficiently in a testaction, which
# returns a true or false value to indicate if last etc, because its unnecessary to check
# for every line.
my @operations = grep { not $_->{done} } @{$filedef->{operations}};
last unless @operations;

chomp $line;

do { $_->{test} // sub { 0 } }->( $line ) and do { $_->{testaction} // $filedef->{testaction} // sub { } }->( $_, $line ) for ( @operations )
}

close $filehandle;

do { $_->{postaction} // $filedef->{postaction} // sub { } }->( $_ ) for ( @{$filedef->{operations}} );
}
}

END
{
print "\nPress enter to exit\n";
<>;
}



Quote
Whoooooohhh !! That's one hell of a code there !!]


It is indeed one hell of a code and covers some more advanced aspects of Perl. As briefly mentioned previously, the aim was to write a more manageable code that supports all your current requirements and potential variations in the future. It is important that you understand what it is doing in order to modify it yourself in the future. If there is anything you don't understand feel free to ask about it. You may wish to use it as a basis to develop the simpler approach that tejas provided instead.

Regards,

Chris


(This post was edited by Zhris on Feb 2, 2015, 8:17 PM)


mohan
User

Feb 2, 2015, 11:55 PM

Post #42 of 51 (8941 views)
Re: [Zhris] Searching for a string [In reply to] Can't Post

Awesome !!It's works perfectly !!

Thanks a million and tejas too, for helping out !!

I would love to learn code this way !! Any particular advice on how to proceed ? I just have the basic knowledge !


Zhris
Enthusiast

Feb 3, 2015, 8:51 AM

Post #43 of 51 (8929 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

Hi,

No problem.

My style of coding comes from experience. There's always more than one way to do the same thing in Perl, over time you will broaden your knowledge and ability to code most appropriately for a particular problem. The key aspects we are dealing with here specifically are nested data structures and code references. My advice on how to proceed is to read through the O'Reilly range of Perl books and Modern Perl while regularly trying to apply your gained knowledge by solving fictitious problems. If you have an active interest in Perl, following Perl forums exposes you to a mixture of problems of all shapes and forms, which you can try and solve yourself then compare your solution with those who answered.

Goodluck,

Chris


mohan
User

Feb 8, 2015, 9:38 PM

Post #44 of 51 (8855 views)
Re: [Zhris] Searching for a string [In reply to] Can't Post

Thanks for the advice !! :) Will get in touch with you in case of any doubts :)


Tejas
User

Feb 16, 2015, 1:25 AM

Post #45 of 51 (8635 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

Zhris's solutions would always make u learn new things for solving our problem.
Understand what he has been doing all through the code, rather than just using it for a purpose.
There is a lot of perl stuff he is doing which i assume u already figured .

Thanks
Tejas


Laurent_R
Veteran / Moderator

Feb 16, 2015, 9:54 AM

Post #46 of 51 (8626 views)
Re: [mohan] Searching for a string [In reply to] Can't Post


In Reply To
Awesome !!It's works perfectly !!

Thanks a million and tejas too, for helping out !!

hanks to me.

You might also have extended your thanks to me. Wink


mohan
User

Feb 18, 2015, 1:16 AM

Post #47 of 51 (8586 views)
Re: [Laurent_R] Searching for a string [In reply to] Can't Post

Oh my bad ! Very sorry...don't know how I missed your name ! Thanks a lot :)


mohan
User

Feb 18, 2015, 1:24 AM

Post #48 of 51 (8585 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post

Sure !


Tejas
User

Feb 18, 2015, 1:28 AM

Post #49 of 51 (8584 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

All I know in Perl is just because of Laurent ,chris ,bill and fishmonger
They are the four persons behind everything that I have done .
They have solved lots of problems Which I thought would never be done so easily.

Thanks


mohan
User

Feb 19, 2015, 12:27 AM

Post #50 of 51 (8566 views)
Re: [Tejas] Searching for a string [In reply to] Can't Post

Whoa ! That's great to hear ! Hope they can support and train me as well ! Smile


Laurent_R
Veteran / Moderator

Feb 19, 2015, 10:55 AM

Post #51 of 51 (2963 views)
Re: [mohan] Searching for a string [In reply to] Can't Post

Of course I'll gladly support you and, although I can't speak of the name of the other three individuals mentioned by Tejas, I am fairly sure that they will also be willing to help you.
Smile

To Tejas: thank you for your appreciation.


(This post was edited by Laurent_R on Feb 20, 2015, 12:07 AM)

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives