Does archname directory get scanned automatically? - perl

When I want to provide directory to include modules I write:
perl -Ilib -Isome/dir script.pl
Should I include archname directory too or is that scanned automatically?
from Makefile:
{APP_ROOT}/local/lib/perl5/${shell perl -MConfig -e 'print $$Config{archname}'}
UPD
perl -V output:
/home/kes/perl5/perlbrew/perls/perl-5.24.0/lib/site_perl/5.24.0/x86_64-linux
/home/kes/perl5/perlbrew/perls/perl-5.24.0/lib/site_perl/5.24.0
/home/kes/perl5/perlbrew/perls/perl-5.24.0/lib/5.24.0/x86_64-linux
/home/kes/perl5/perlbrew/perls/perl-5.24.0/lib/5.24.0

archname is included in #INC by default if it exists:
perl -MConfig -E 'say $_ for ($Config{archname}, #INC)'
x86_64-linux
/home/user/perl5/perlbrew/perls/perl-5.24.1/lib/site_perl/5.24.1/x86_64-linux
/home/user/perl5/perlbrew/perls/perl-5.24.1/lib/site_perl/5.24.1
/home/user/perl5/perlbrew/perls/perl-5.24.1/lib/5.24.1/x86_64-linux
/home/user/perl5/perlbrew/perls/perl-5.24.1/lib/5.24.1
UPD
It will be added if it exists:
perl -Isomedir -e 'local $"="\n"; print "#INC"'
somedir
/home/kes/perl5/perlbrew/perls/perl-5.24.0/lib/site_perl/5.24.0/x86_64-linux
/home/kes/perl5/perlbrew/perls/perl-5.24.0/lib/site_perl/5.24.0
/home/kes/perl5/perlbrew/perls/perl-5.24.0/lib/5.24.0/x86_64-linux
/home/kes/perl5/perlbrew/perls/perl-5.24.0/lib/5.24.0
mkdir -p somedir/x86_64-linux
perl -Isomedir -e 'local $"="\n"; print "#INC"'
somedir/x86_64-linux
somedir
/home/kes/perl5/perlbrew/perls/perl-5.24.0/lib/site_perl/5.24.0/x86_64-linux
/home/kes/perl5/perlbrew/perls/perl-5.24.0/lib/site_perl/5.24.0
/home/kes/perl5/perlbrew/perls/perl-5.24.0/lib/5.24.0/x86_64-linux
/home/kes/perl5/perlbrew/perls/perl-5.24.0/lib/5.24.0

Yes, if it exists, the arch sub directory will be added to #INC when you add the parent non-arch directory.
Baseline:
$ perl -E'say for #INC' | wc -l
5
Add via -I:
$ perl -Ilib -E'say for #INC' | head -n -5
lib/5.24.0/x86_64-linux-thread-multi
lib/5.24.0
lib
Add via PERL5LIB:
$ PERL5LIB=lib perl -E'say for #INC' | head -n -5
lib/5.24.0/x86_64-linux-thread-multi
lib/5.24.0
lib
Add via lib.pm:
$ perl -E'use lib qw( lib ); say for #INC' | head -n -5
lib/5.24.0/x86_64-linux-thread-multi
lib/5.24.0
lib
Add via mylib.pm:
$ perl -E'use mylib; say for #INC' | head -n -5
/.../lib/5.24.0/x86_64-linux-thread-multi
/.../lib/5.24.0
/.../lib
It doesn't add them if you add directly to #INC:
$ perl -E'unshift #INC, "lib"; say for #INC' | head -n -5
lib

Related

How to add a line in every file in a directory with perl commandline

I want to add a line at the beginning of every file in a directory.
perl -i.bkp -p -e 'print "#include top_level.reset\n" if $. == 1' *.reset
But this command is updating only the first file in the directory. I think this is because $. is not resetting for next file.
How to modify all the files.
You are correct, $. is not reset between files when processing #ARGV. See perlvar. You can work around it by explicitly closing ARGV on EOF - see eof. But I would not bother, instead I would use the shell to iterate the files:
for f in *.reset; do perl -i.bkp -p -e 'print "#include top_level.reset\n" if $. == 1' $f; done
ls -1 *.reset | xargs -n 1 perl -i.bkp -p -e 'print "#include top_level.reset\n" if $. == 1'

How do I define new make tasks, using `Makefile.PL`?

I would like my generated Makefile to have these new tasks for linting:
perl:
-for f in **/*.pl; do perl -MO=Lint -cw $$f 2>&1 | grep -v "syntax OK"; done
-for f in **/*.pm; do perl -MO=Lint -cw $$f 2>&1 | grep -v "syntax OK"; done
perlcritic:
-perlcritic . | grep -v "source OK"
lint: perl perlcritic
I tried writing a Makefile.PL, but when I run it, the resulting Makefile still lacks the lint task.
use ExtUtils::MakeMaker;
sub MY::lint {
return <<'END';
lint:
echo "Linting!!!!!!!!!!!1"
END
}
WriteMakefile;
I tried reading the CPAN docs, but like most docs, they give snippets without sufficient context, so I'm not even sure if I should declare the subs before or after WriteMakefile.
Also posted on Reddit.
Thanks to briandfoy:
$ cat Makefile.PL
#!/usr/bin/env perl
use strict;
use warnings;
use ExtUtils::MakeMaker;
WriteMakefile;
sub MY::postamble {
return <<'END';
perlwarn:
-find . -type f -name '*.pl' -exec perl -MO=Lint -cw {} 2>&1 \; | grep -v "syntax OK" | grep -v "Can't locate"
-find . -type f -name '*.pm' -exec perl -MO=Lint -cw {} 2>&1 \; | grep -v "syntax OK" | grep -v "Can't locate"
-find . -type f -name '*.t' -exec perl -MO=Lint -cw {} 2>&1 \; | grep -v "syntax OK" | grep -v "Can't locate"
perlcritic:
-perlcritic . | grep -v "source OK"
lint: perlwarn perlcritic
END
}
A solution that works and is slightly easier to maintain is to put the make targets in a separate makefile, so you can benefit of your text editor capabilities and it is a bit easier to read:
# In Makefile.PL
use File::Slurp;
sub MY::postamble {
my $targets = read_file('./script/additional.make');
return $targets;
}
# In /script/additional.make
perl:
for f in **/*.pl; do perl -MO=Lint -cw $$f 2>&1 | grep -v "syntax OK"; done
for f in **/*.pm; do perl -MO=Lint -cw $$f 2>&1 | grep -v "syntax OK"; done
perlcritic:
perlcritic . | grep -v "source OK"
lint: perl perlcritic
Note for later readers: I am using Module::Install and it was necessary to use :: as separators because it seems that Module::Install forbid to mix : and ::. It also disallow the use of -.

grep lines matching the pattern using perl programming

i want to grep pattern from a large file. But using grep it is very slow and pattern to be grep is also case insensitive. So , i read that perl is faster for file reading. Someone please tel me a way to do it in perl.
Thanks.
cat File1.txt File2.txt | grep -in "exception" | grep -v "pattern"
In perl:
perl -ne 'print "$.:$_" if /exception/i and !/pattern/' File1.txt File2.txt
or without cat:
grep -in "exception" File1.txt File2.txt | grep -v "pattern"
I am doubtful that Perl would give you a performance advantage in this area. The grep utility is a pre-compiled binary written in C; Perl is an interpreted language and bears an extra performance overhead which e.g. GNU grep does not. If grep is slow the bottleneck is most likely the file being loaded from disk into main memory. How big is the file?
FYI, grep has flags which enable case-insensitive matching and Perl-style regex syntax.
% grep -i 'abc' <file> # Matches abc, ABC, aBc, etc.
% grep -i 'ab\|cd' <file> # Matches ab or cd
% grep -P 'ab|cd' <file> # Matches ab or cd
An equivalent Perl program is:
# grep.pl
$pat = shift;
while(<>) { if(/$pat/i) { print; } }
which can be invoked as
perl grep.pl abc file1.txt file2.txt ...
My advice, stick with grep.
grep -i 'pattern' file->perl -lne 'print if(/pattern/i)' file
grep -vi 'pattern' file->perl -lne 'print unless(/pattern/i)' file
If you want everything with line numebrs as well, the replace the print
with print "$. $_" in the above commands

How to tell if my program is being piped to another (Perl)

"ls" behaves differently when its output is being piped:
> ls ???
bar foo
> ls ??? | cat
bar
foo
How does it know, and how would I do this in Perl?
In Perl, the -t file test operator indicates whether a filehandle
(including STDIN) is connected to a terminal.
There is also the -p test operator to indicate whether a filehandle
is attached to a pipe.
$ perl -e 'printf "term:%d, pipe:%d\n", -t STDIN, -p STDIN'
term:1, pipe:0
$ perl -e 'printf "term:%d, pipe:%d\n", -t STDIN, -p STDIN' < /tmp/foo
term:0, pipe:0
$ echo foo | perl -e 'printf "term:%d, pipe:%d\n", -t STDIN, -p STDIN'
term:0, pipe:1
File test operator documentation at perldoc -f -X.
use IO::Interactive qw(is_interactive);
is_interactive() or warn "Being piped\n";

calling perl subroutine in shell script

i made a Perl Module MyModule.pm it has some subroutines getText which I wanted to call in a shell script.
i tried following manner but it gives error;
SEC_DIR=`perl -MMyModule -e 'getText'`; # line 1
echo $SEC_DIR
exit 0
Returned Error;
Can't locate MyModule.pm in #INC (#INC contains: /usr/lib/perl5/5.10.0/x86_64-linux-thread-multi /usr/lib/perl5/5.10.0 /usr/lib/perl5/site_perl/5.10.0/x86_64-linux-thread-multi /usr/lib/perl5/site_perl/5.10.0 /usr/lib/perl5/vendor_perl/5.10.0/x86_64-linux-thread-multi /usr/lib/perl5/vendor_perl/5.10.0 /usr/lib/perl5/vendor_perl .).
BEGIN failed--compilation aborted.
PS: .pm file and .sh are at same location.
some other options I tried;
line 1:
SEC_DIR=`perl -MMyModule -e '&getText'`;
SEC_DIR=`perl -MMyModule -e 'use MyModule; getText'`;
SEC_DIR=`perl -e 'use MyModule; getText'`;
It's hard to say what went wrong not knowing what's in MyModule.pm.
#INC looks ok (. is in the list, so there should be no problem with locating MyModule.pm in current directory).
Here's a minimal example that works the way you described. Hope it helps.
$ cat SomeModule.pm
package SomeModule;
sub testsub
{
return "it works\n";
}
1;
$ VAL=`perl -I. -MSomeModule -e 'print SomeModule::testsub'`
$ echo $VAL
it works
Another way to load the module would be:
$ perl -e 'require "./SomeModule.pm"; print SomeModule::testsub()'
it works