I have a string like this , how are you , I want to get all possible shuffle of word like
how are you
are how you
you how are
you are how
are you how
how you are
How can I make it in perl script , i've tried the shuffle function but it returns only one string of shuffle .
If you are not familiar with Perl script, you can tell me the logic only.
Note: The words count in string are not constant.
What you're talking about are permutations. This can be done in Perl with the Algorithm::Permute module:
If you've installed the module, here's a shell one-liner that will do it for you:
perl -e'
use Algorithm::Permute qw();
my $str = $ARGV[0];
my #arr = split(/\s+/,$str);
my $ap = new Algorithm::Permute(\#arr);
while (my #res = $ap->next()) { print("#res\n"); }
' 'how are you';
## you are how
## are you how
## are how you
## you how are
## how you are
## how are you
You can use List::Permutor CPAN module:
use strict;
use warnings;
use List::Permutor;
my $perm = new List::Permutor qw/ how are you /;
while (my #set = $perm->next)
{
print "#set\n";
}
Output:
how are you
how you are
are how you
are you how
you how are
you are how
As bgoldst suggested Algorithm::Permute, for faster execution you can write this without using while loop:
use Algorithm::Permute;
my #array = qw(how are you);
Algorithm::Permute::permute {
print "#array\n";
}#array;
Related
If one string is expressed like below
$str = "5+2-1";
I'd like to get the calculation result from that string.
How do I convert to scalar to compute this?
Thanks.
The easiest way to do this:
print eval('5+2-1');
but it's not safe:
print eval('print "You are hacked"');
You need to check string before eval it.
Also you can use Math::Expression module or many other modules from cpan:
#!/usr/bin/perl
use strict;
use warnings;
use Math::Expression;
my $env = Math::Expression->new;
my $res = $env->Parse( '5+2-1' );
# my $res = $env->Parse( 'print you are hacked' ); # no math expression here
print $env->Eval( $res );
If you are sure the string does not contain any malicious code you can use eval to treat the content of it as perl code.
#!/usr/bin/perl
use strict;
use warnings;
my $string = "5+2-1";
print eval($string);
#print 6
I started using Term::Readline recently, but now I realized cat text | ./script.pl doesn't work (no output).
script.pl snippet before (working ok):
#!/usr/bin/perl
use strict;
use warnings;
$| = 1;
while (<>) {
print $_;
}
script.pl snippet after (working only interactively):
#!/usr/bin/perl
use strict;
use warnings;
use Term::ReadLine
$| = 1;
my $term = Term::ReadLine->new('name');
my $input;
while (defined ($input = $term->readline('')) ) {
print $input;
}
Is there anything I can do to preserve this behavior (to have the lines printed) ?
You need to set it up to use the input and output filehandles that you want. The docs don't spell it out, but the constructor takes either a string (to serve as a name), or that string and globs for input and output filehandles (need both).
use warnings;
use strict;
use Term::ReadLine;
my $term = Term::ReadLine->new('name', \*STDIN, \*STDOUT);
while (my $line = $term->readline()) {
print $line, "\n";
}
Now
echo "hello\nthere" | script.pl
prints the two lines with hello and there, while scipt.pl < input.txt prints out the lines of the file input.txt. After this the normal STDIN and STDOUT will be used by the module's $term for all future I/O. Note that the module has methods for retrieving input and output filehandles ($term->OUT and $term->IN) so you can change later where your I/O goes.
The Term::ReaLine itself doesn't have much detail but this is a front end for other modules, listed on the page. Their pages have far more information. Also, I believe that uses of this are covered elsewhere, for example in the good old Cookbook.
I have the following perl script, that takes in a parameters' file and stores it into a hash. I want to modify & pass this hash to another perl script that I am calling using the system command:
script1.pl
#!/usr/bin/perl -w
# usage perl script1.pl script1.params
# script1.params file looks like this:
# PROJECTNAME=>project_dir
# FASTALIST=>samples_fastq.csv
use Data::Dumper;
my $paramfile = $ARGV[0];
# open parameter file
open PARAM, $paramfile or die print $!;
# save it in a hash
my %param;
while(<PARAM>)
{
chomp;
#r = split('=>');
$param{$r[0]}=$r[1];
}
# define directories
# add to parameters' hash
$param{'INDIR'} = $param{'PROJECTNAME'}.'/input';
$param{'OUTDIR'} = $param{'PROJECTNAME'}.'/output';
.... do something ...
# #samples is a list of sample names
foreach (#samples)
{
# for each sample, pass the hash values & sample name to a separate script
system('perl script2.pl <hash> $_');
}
script2.pl
#!/usr/bin/perl -w
use Data::Dumper;
## usage <script2.pl> <hash> <samplename>
# something like getting and printing the hash
my #string = $ARGV[0];
print #string;
If you can help me showing how to pass and get the hash object (something simple like printing the hash object in the second script would do), then I'd appreciate your help.
Thanks!
What you're looking for is something called serialisation. It's difficult to directly represent a memory structure in such a way as to pass it between processes, because of all sorts of fun things like pointers and buffers.
So you need to turn your hash into something simple enough to hand over in a single go.
Three key options for this in my opinion:
Storable - a perl core module that lets you freeze and thaw a data structure for this sort of purpose.
JSON - a text based representation of a hash-like structure.
XML - bit like JSON, but with slightly different strengths/weaknesses.
Which you should use depends a little on how big your data structure is.
Storable is probably the simplest, but it's not going to be particularly portable.
There's also Data::Dumper that's an option too, as it prints data structures. Generally though, I'd suggest that has all the downsides of all the above - you still need to parse it like JSON/XML but it's also not portable.
Example using Storable:
use strict;
use warnings;
use Storable qw ( freeze );
use MIME::Base64;
my %test_hash = (
"fish" => "paste",
"apples" => "pears"
);
my $frozen = encode_base64 freeze( \%test_hash );
system( "perl", "some_other_script.pl", $frozen );
Calling:
use strict;
use warnings;
use Storable qw ( thaw );
use Data::Dumper;
use MIME::Base64;
my ($imported_scalar) = #ARGV;
print $imported_scalar;
my $thing = thaw (decode_base64 $imported_scalar ) ;
print Dumper $thing;
Or:
my %param = %{ thaw (decode_base64 $imported_scalar ) };
print Dumper \%param;
This will print:
BAoIMTIzNDU2NzgEBAQIAwIAAAAKBXBhc3RlBAAAAGZpc2gKBXBlYXJzBgAAAGFwcGxlcw==
$VAR1 = {
'apples' => 'pears',
'fish' => 'paste'
};
Doing the same with JSON - which has the advantage of being passed as plain text, and in a general purpose format. (Most languages can parse JSON):
#!/usr/bin/env perl
use strict;
use warnings;
use JSON;
my %test_hash = (
"fish" => "paste",
"apples" => "pears"
);
my $json_text = encode_json ( \%test_hash );
print "Encoded: ",$json_text,"\n";
system( "perl", "some_other_script.pl", quotemeta $json_text );
Calling:
#!/usr/bin/env perl
use strict;
use warnings;
use JSON;
use Data::Dumper;
my ($imported_scalar) = #ARGV;
$imported_scalar =~ s,\\,,g;
print "Got: ",$imported_scalar,"\n";
my $thing = decode_json $imported_scalar ;
print Dumper $thing;
Need the quotemeta and the removal of slashes unfortunately, because the shell interpolates them. This is the common problem if you're trying to do this sort of thing.
I want to pass a hash reference as an argument from one perl script (script1.pl) to another perl script (script2.pl). This is how my code looks:
----------------------------script1.pl---------------------------------
#!/usr/bin/perl -w
use strict;
use warnings;
my %hash = (
'a' => "Harsha",
'b' => "Manager"
);
my $ref = \%hash;
system "perl script2.pl $ref";
----------------------------script2.pl---------------------------------
#!/usr/bin/perl -w
use strict;
use warnings;
my %hash = %{$ARGV[0]};
my $string = "a";
if (exists($hash{$string})){
print "$string = $hash{$string}\n";
}
And this is the output error:
sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `perl script2.pl HASH(0x8fbed0)'
I can't figure out the right way to pass the reference.
A hash is an in memory data structure. Processes 'own' their own memory space, and other processes can't just access it. If you think about it, I'm sure you'll spot why quite quickly.
A hash reference is an address of that memory location. Even if the other process could 'understand' it, it still wouldn't be able to access the memory space.
What we're talking about here is actually quite a big concept - Inter Process Communication or IPC - so much so there's a whole chapter of the documentation about it, called perlipc.
The long and short of it is this - you can't do what you're trying to do. Sharing memory between processes is much more difficult than you imagine.
What you can do is transfer the data back and forth - not by reference, but the actual information contained.
I would suggest that for your example, the tool for the job is JSON, because then you can encode and decode your hash:
#!/usr/bin/perl -w
use strict;
use warnings;
use JSON;
my %hash = (
'a' => "Harsha",
'b' => "Manager"
);
my $json_string = to_json( \%hash );
print $json_string;
This gives:
{"b":"Manager","a":"Harsha"}
Then your can 'pass' your $json_string - either on the command line, although bear in mind that any spaces in it confuses #ARGV a bit if you're not careful - or via STDIN.
And then decode in your sub process:
use strict;
use warnings;
use JSON;
my $json_string = '{"b":"Manager","a":"Harsha"}';
my $json = from_json ( $json_string );
my $string = "a";
if (exists($json -> {$string} )){
print "$string = ",$json -> {$string},"\n";
}
(You can make it more similar to your code by doing:
my $json = from_json ( $json_string );
my %hash = %$json;
Other options would be:
use Storable - either freezing and thawing ( memory) or storing and retrieving (disk)
use IPC::Open2 and send data on STDIN.
There's a variety of options really - have a look at perlipc. But it's not as simple a matter as 'just passing a reference' unfortunately.
Use Storable to store data in first script and retrieve it from other.
firstscript.pl
store (\%hash, "/home/chankey/secondscript.$$") or die "could not store";
system("perl", "secondscript.pl", $$) == 0 or die "error";
secondscript.pl
my $parentpid = shift;
my $ref = retrieve("/home/chankey/secondscript.$parentpid") or die "couldn't retrieve";
print Dumper $ref;
You've received the %hash in $ref. Now use it the way you want.
You can't pass a reference from one script to another - that reference only has meaning within the currently running instance of perl.
You would need to "serialise" the data in the first script, and then "deserialise" it in the second.
Your way of calling perl file is wrong.
Just change the way of calling it and you are done.
Script1.pl
---------------------------------
#!/usr/bin/perl -w
use strict;
use warnings;
my %hash = (
'a' => "Harsha",
'b' => "Manager"
);
system("perl","script2.pl",%hash);
Use this %hash in another perl script as shown below.
Script2.pl
----------------------------------
#!/usr/bin/perl -w
use strict;
use warnings;
my %hash = #ARGV;
my $string = "a";
if (exists($hash{$string})){
print "$string = $hash{$string}\n";
}
OutPut is
a = Harsha
I need to know the CGI variables in my script. I know I can use
$query->param()
to get CGI parameters, but how can I get module paths and the version of Perl?
you question is really vague..
to get the complete environment and all installed modules use this:
#!"\xampp\perl\bin\perl.exe"
use strict;
use warnings;
use File::Find ;
use CGI qw(:standard);
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
# use sneaky cgi direct printing ;)
$|=1 ;
# define subs
sub permodules;
# print header
print header;
print start_html("Environment");
# get perl version
print `perl -v`;
# get env vars
foreach (sort keys %ENV) {
print $ENV{$_};
}
# get inc vars
print #INC;
foreach my $path (#INC) {
next if ($path =~ /^\./) ;
find(\&perlmodules,$path) ;
}
# get mods
my (#mods,%mods);
#mods=sort {lc($a) cmp lc($b)} keys %mods;
my $amount=int($#mods/3+.9999) ;
for (my $mod=0 ; $mod<$amount ; $mod++) {
print $mods[$mod] . "-" . $mods[$mod+1*$amount] . "-" . $mods[$mod+2*$amount] ;
}
sub perlmodules {
if ($File::Find::name =~ /\.pm$/){
open(MODFILE,$File::Find::name) || return;
while(<MODFILE>){
if (/^ *package +(\S+);/) {
$mods{$1}=1 ;
last;
}
}
close(MODFILE) ;
}
}
# end
print end_html;
adapt the print statements to fit your needs.
Yes, everything is stored in the %ENV hash. Here's a good example of how to display them:
#!/usr/bin/perl -wT
use strict;
use CGI qw(:standard);
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
print header;
print start_html("Environment");
foreach my $key (sort(keys(%ENV))) {
print "$key = $ENV{$key}<br>\n";
}
print end_html;
EDIT: Alex's answer is more comprehensive, and will return module information as well.
Read the docs they are very good.
http://perldoc.perl.org/CGI.html
They cover almost everything you'll run into.
%ENV and such
http://perldoc.perl.org/CGI.html#FETCHING-ENVIRONMENT-VARIABLES
When you "use" a module (i.e., "use File::Find;") Perl loads the first occurrence of that module that it finds in the #INC and sticks it into %INC. For example, if you're looking to find which version of File::Find you're using, you can simply print the corresponding entry from %INC.
The command will look like this:
perl -MFile::Find -e 'print $INC{"File/Find.pm"} . "\n";'
Which prints this on my mac:
/usr/local/ActivePerl-5.16/lib/File/Find.pm