If
you have a question on how to do something in Perl, or
you need a Perl solution to an actual real-life problem, or
you're unsure why something you've tried just isn't working...
then this section is the place to ask.
However, you might consider asking in the chatterbox first (if you're a
registered user). The response time tends to be quicker, and if it turns
out that the problem/solutions are too much for the cb to handle, the
kind monks will be sure to direct you here.
Emacs comes with two different major modes to edit Perl code: perl-mode and cperl-mode.
perl-mode is somewhat stuck with the Perl syntax of 5.14, has less features, but a cleaner implementation. cperl-mode is up to date with Perl 5.38 and has deeper understanding of Perl syntax, but a somewhat arcane implementation, most of it written in the previous century.
With all due respect to TIMTOWTDI, maintaining two major modes turns out to be not enough fun in the long run, and last week Stefan Kangas opened a wishlist item to Making perl-mode.el obsolete.
The mail thread shows that some people prefer perl-mode because it is less "colorful" and intrusive than cperl-mode. Therefore, the idea is to enable cperl-mode to (optionally) look like and behave like perl-mode. That way, perl-mode.el can be obsoleted without making those users uncomfortable: perl-mode would continue to exist as a custom theme of cperl-mode.
Users of perl-mode are now encouraged to try cperl-mode, and to report bugs against cperl-mode where they prefer the behavior of perl-mode. This has already started. The "current" cperl-mode.el is available from the repository: cperl-mode.el and is supposed to work with Emacs 26 and newer.
I very much appreciate the thorough answers I receive here: they have helped me get reacquainted with Perl. The hardest part I still encounter is to understand what the symbols mean, not so much the concepts.
I'm simply asking for a "better" way to accomplish a task I already can do.
An example: I want to know if there's a way to send just one key & value per array/hash - preferably by reference - to a subroutine. In the example code below, I want to send all and only the {Sub_Name}s and their respective values. The code below works and I've come up with two ways to list the Sub_Name. I'm simply wanting to know if there's a better way to do it, so I don't have to make an array or send the entire array of hashes to the subroutine.
#!/usr/bin/env perl
#use 5.36.1;
use strict;
use warnings;
use Data::Dumper;
use autodie;
use File::Find;
use File::Copy;
use File::Rename;
use feature 'fc';
use File::Path qw( make_path );
my $Wait_Time = 10; # Implement Time Delay
# Subscription DATA sets
my @Subscription = (
{
Sub_Name => "Morph",
Archive_File => "Morph Archive.txt",
},
{
Sub_Name => "Analogue",
Archive_File => "Analogue Archive.txt",
},
{
Sub_Name => "Cat",
Archive_File => "Cat Archive.txt",
},
{
Sub_Name => "Zoonotic",
Archive_File => "Zoonotic Archive.txt",
},
{
Sub_Name => "Hydro",
Archive_File => "Hydro Archive.txt",
},
);
#Subscription of Names
my @Subscription_Names_List;
for (@Subscription) {push @Subscription_Names_List, $_->{Sub_Name};}
List_Subscriptions(\@Subscription_Names_List);
for (@Subscription) {
Display_Subs(\%$_);
}
sub Display_Subs {
my ($my_Sub) = @_;
print "Testing Subscription to: $my_Sub->{Sub_Name}\n";
return $my_Sub;
}
sub List_Subscriptions {
my (@Sub_ARRAY) = @{$_[0]};
# my (@Sub_ARRAY) = @_;
print "The Current Subscription List:\n\n";
for (@Sub_ARRAY) { print " \t$_ \n"; }
print "\n\n";
}
Is it better to use a "packaged" easily installable version of Perl such as Strawberry on a Windows OS or to compile a version or there is no practical difference, etc...?
I primarily ask for two reasons: stability and speed. An underlying assumption to both reasons is that compiling code will always be faster, because it will compile based on specific chipsets and its respective native math libraries.
1. Stability. My systems run both AMD CPUs and GPUs. I have wondered if instability in GAMES are sometimes caused by various issues of the binaries being compiled for Intel CPUs and NVidia GPUs. By extension, is there an inherent stability benefit of compiling Perl on a Windows system?
2. Speed. This likely has no real practical value unless one is running a "large" server on Windows; but, I wanted to ask anyway. So, by a similar analogy to GAMES stability, since there is a real benefit to GAMES which have been optimized for either AMD or Intel/NVidia and sometimes specifically a chipset, is there a speed benefit to compiling Perl on Windows?
The was the SO question recently, and as it sometimes happens, when I think "oh, this can be fun to play with, for better algorithm", it brewed for itself somewhere in subconscious, until the eureka moment a couple days ago (I'm in no hurry :-)): "Of course! Be greedy, demand twice as needed!"
There was advice to use brute force, at least as accepted answer in linked question (from 2021) there. Not sure if I got it right, I don't read Ruby, and didn't try other answers. Both brute subroutines below aren't actually used: they are totally unusable for lists with ~15 unique strings or more, plus any decent amount of duplicates. I wrote 2nd one because I couldn't believe it at first (accepted solution??). They are left just in case anyone wants to try (or point at my mistakes in implementation?), and can be ignored.
Back to answers at SO, there are 2 Perl solutions. One (a) doesn't compile; (b) if fixed, emits a warning for un-initialized value; (c) if fixed (or ignored), it seems to work OK. But for (corner-case, of course) input of (b,a,a), it gives answer (b,a). I didn't look further.
Another solution (by esteemed monk) fails randomly for e.g. corner-case (a,a,a,b,b) -- the only answer can be (a,b,a,b,a), of course. Why does it fail? Output list is initialized to e.g. (a,b). If 1st key to iterate is "a", then one of 2 remaining "a"'s is added to give (a,b,a) with no place for 2nd remaining "a". So, easy fix would be kind of "breadth-first" hash consumption. I'm sorry if code I had to add looks ugly to the author.
This fixed version will serve as reference to compare my solution to, it generates truly random lists.
With algorithm I suggest -- ask for twice as many random indexes from remaining pool, then simply reject (comb out) half of them. It guarantees there will be no consecutive dupes (and of course doesn't mean "only odd or even indexes for this value").
One obvious compromise on randomness will be "dupes are never placed at both head and tail" -- except corner-cases such as 'aba' or 'abaca', of course. There are actually 3 cases, depending on size of remaining pool. Cases "2" and "3" restrict randomness further. E.g., for 'aaaabbbcc', the 'c' is never placed at indexes 0 or 1 -- unlike the "reference SO implementation with true randomness".
However, lines with "die" in them can be un-commented (and they were un-commented during benchmarking) if input is not an artificial corner-case -- this code is never reached with realistic data. I mean, other than corner-cases and head/tail restriction, my algorithm seems to produce random enough result.
(In fact, one of "requests" of "RFC" is how to estimate randomness (entropy) for multiple runs of subroutine. Didn't look into that yet.)
Further "requests" are: can it be improved? Both List::MoreUtils::samples and e.g. (unused) Math::Prime::Util::randperm return their result shuffled, which I don't need and have to sort back to order! And more, e.g. samples takes random samples and therefore should know which items were unselected, but I have no better way to find out "which" except with more work using singleton. It feels like huge amount of unnecessary work I do (though it's still much faster than "SO reference solution"). Or maybe, perhaps, someone would suggest even faster solution?
(+ I understand there's sloppiness on my side in e.g. $uniq variable name doesn't actually mean number of unique items which fake_data returns. I hope this (and similar) can be forgiven.)
use strict;
use warnings;
use feature 'say';
use List::Util qw/ shuffle /;
use List::MoreUtils qw/ part samples singleton /;
use ntheory qw/ forperm lastfor /;
use Algorithm::Combinatorics qw/ permutations /;
use Benchmark 'cmpthese';
my @input = shuffle( qw( a a a a b b b c c )); # corner-cases
@input = shuffle( qw( a a a b b )); #
srand 123;
@input = fake_data( 555, 55 );
#say scalar @input; # 2096
sub fake_data {
my ( $uniq, $pivot ) = @_;
my @tmp = map { sprintf '< %06d >', rand 1e9 } 0 ... $uniq;
my @out;
push @out, @tmp[ 0 .. $_ ] for 0 .. $pivot;
@out = shuffle( @out, @tmp[ $pivot + 1 .. $uniq ]);
return @out
}
cmpthese 10, {
SO_fixed => sub { die unless SO_fixed( \@input )},
my_shuffle => sub { die unless my_shuffle( \@input )},
};
sub brute {
my $input_ref = shift;
my @output;
forperm {
my $prev = '';
for ( @_ ) {
return if $prev eq $input_ref-> [ $_ ];
$prev = $input_ref-> [ $_ ]
}
@output = @{ $input_ref }[ @_ ];
lastfor, return
} @$input_ref;
return \@output
}
sub brute2 {
my $input_ref = shift;
my @output;
my $iter = permutations( $input_ref );
PERM: while ( my $p = $iter-> next ) {
my $prev = '';
for ( @$p ) {
next PERM if $prev eq $_;
$prev = $_
}
@output = @$p;
last PERM
}
return \@output
}
sub SO_fixed {
my $input_ref = shift;
my %counts; ++$counts{ $_ } for @$input_ref;
my @strings = shuffle keys %counts;
LOOP: {
my $any = 0;
for my $string ( keys( %counts ) ) {
next if $counts{ $string } == 1;
$counts{ $string } --;
$any = 1;
my @safe =
grep { $_ == 0 || $strings[ $_ - 1 ] ne $string
+ }
grep { $_ == @strings || $strings[ $_ ] ne $string
+ }
0 .. @strings;
return undef unless @safe;
my $pick = $safe[ rand( @safe ) ];
splice( @strings, $pick, 0, $string );
}
redo LOOP if $any
}
return \@strings
}
sub my_shuffle {
my $input_ref = shift;
my @output;
my %counts; $counts{ $_ } ++ for @$input_ref;
my ( $single, $multi ) = part { $counts{ $_ } > 1 } keys %counts;
my @multi = sort { $counts{ $b } <=> $counts{ $a }} @$multi;
my @pool = ( 0 .. $#$input_ref );
for my $str ( @multi ) {
my $count = $counts{ $str };
my @take;
if ( $count <= @pool / 2 ) {
# case 1
my @excess = sort { $a <=> $b } samples( 2 * $count, @pool
+ );
my $n = int rand 2;
my @idx = grep { $n ^ $_ % 2 } 0 .. $#excess;
@take = @excess[ @idx ];
}
elsif ( 2 * $count - 1 == @pool ) {
# case 2
#die 'This code is unreachable for realistic input';
my @idx = grep { not $_ % 2 } 0 .. $#pool;
@take = @pool[ @idx ];
}
else {
# case 3
#die 'This code is unreachable for realistic input';
my $prev = -2;
my @ok = grep {
my $res = $_ - $prev;
$prev = $_;
$res > 1
} @pool;
return undef if $count > @ok;
@take = samples( $count, @ok );
}
@pool = singleton @pool, @take;
@output[ $_ ] = $str for @take;
}
@output[ @pool ] = @$single if @pool;
return \@output;
}
__END__
(warning: too few iterations for a reliable count)
Rate SO_fixed my_shuffle
SO_fixed 2.29/s -- -95%
my_shuffle 42.7/s 1763% --
I'm using the following subroutine to send a binary (PDF) file back to the client's browser.
# IMPORTANT MODULES FOR THIS CODE...
use CGI qw(-utf8);
use File::Spec::Functions qw( catfile );
sub send_file {
my ($cgi, $dir, $file) = @_;
# $dir = '/var/www/download/';
# $file = 'MyLaTeXDocument.pdf';
my $path = catfile($dir, $file);
open my $fh, '<:raw', $path or die "Cannot open '$path': $!\n";
$cgi->charset(''); #REMOVES PRIOR UTF-8 SETTING, AS THIS IS BINARY
+ FILE
print $cgi->header(
-type => 'application/octet-stream',
-attachment => $file,
);
binmode STDOUT, ':raw';
print while <$fh>;
close $fh or die "Cannot close '$path': $!";
return;
}
Why won't the browser just open the "Save as..." dialogue? As it stands, the browser appears to do nothing, silently dropping this activity in background. What is lacking in this code?
PerlMaven has an interesting example that is short by one additional array characterization--one which I have searched for online in vain. Here is his example:
my $one_string = "hello world";
say length $one_string; # 11
my @many_strings = ("abc", "cd", "e", "fg", "hi", "hello world");
say length @many_strings; # 1
say scalar @many_strings; # 6
package Methods {
use strict;
use warnings;
use feature qw(isa);
use Logic::Easy;
no warnings qw(redefine);
sub frobnicate : Multi(frobnicate) {
SIG [$o] where {$o isa 'Foo'};
qq(foo);
}
sub frobnicate : Multi(frobnicate) {
SIG [$o] where {$o isa 'Bar'};
qq(bar);
}
1;
}
__END__
#!/usr/bin/env perl
use strict;
use warnings;
use lib q(.);
use Bar;
use Foo;
use Methods;
use feature qw(say);
my $gizmo = Foo->new();
my $mojo = Bar->new();
# dd $gizmo, $mojo;
say Methods::frobnicate($_) for
($gizmo, $mojo);
__END__
As expected, frobnicate cannot be imported - "there can be only one". Also with Methods->frobnicate() it does not work. Remains only Methods::frobnicate() - as to see. Or is there something else I have overlooked?
I'm creating an XML array with Perl. One line of the XML can potentially contain many characters. Generally it's not an issue. But sometimes the line gets truncated at some arbitrary point, like:
<tag>many characters ends abruptly here in the middl</tag>
I save the line in a scalar array element, then print the entire array. The result has the begin and end tag, but the line in the middle is truncated. In the last fail, it truncated at 23,052 characters which didn't seem like a particularly significant number. In other cases the line greatly exceeds that length, without truncation.
Ideas of why this happens on some lines and not others, or better ways to save these long lines with are appreciated. Maybe more than one tag? I studied MAX XML tag-contents restrictions, as well as Perl scalar length limits, and I don't see any specific limits.
I'm not even invoking taint in the script--but it seems that taint is active (is this because of the Perl version? more on that below), and crashes the program for one simple line:
my @fonts = `/usr/bin/fc-list : family`;
My perl version is:
perl -v
This is perl 5, version 34, subversion 0 (v5.34.0) built for x86_64-li
+nux-gnu-thread-multi
(with 58 registered patches, see perl -V for more detail)
The error that appears in my logs is: "Insecure $ENV{PATH} while running with -T switch . . .," despite the fact that my shebang line has only #!/usr/bin/perl and, while narrowing the problem down, I have disabled all module uses except one: use CGI qw(-utf8);.
As is clear to be seen, there are no variables, nor any executable code, inside the backticks--so there should be no legitimate security issue worthy of shutting down the execution of the script. They invoke a standard command which is useful for displaying the fonts available and installed on the server. Should those fonts change, such as if more were to be installed, the next run of the script would automatically show this--which is what I want.
But even if I put ls inside those backticks, the whole script will fail, and I get "Internal Server Error" as the message in my browser.
Other options than using backticks seem cludgy at best, and problematic at worst. I could run a cronjob that writes the output of this command to a file, then the perl script reads from that file. To be up-to-date, this cronjob would have to run often, consuming server resources--not to mention the added unnecessary file to be stored in the system.
I could use a system call (assuming taint would allow this--I haven't tried it yet) that would do what the cronjob does, then, after opening and reading the file, I could unlink it. This requires multiple steps, much more code, involves file permissions which create potential failure points, and just seems quite rather unperlish.
I fell in love with perl years ago when it gave me the ability to do what I wanted in easy and intuitive ways. This taintedness is rubbing against the grain.
Why is taint even forced on the script without my having invoked it? In actual fact, I would like the script to run with taint, but I need to be able to run this command, too. Is this as impossible as wanting to have my cake and eat it too?
Hey guys, I need a regex that can check if a string contains exactly two 'x' and one '/', and some numbers, like in this example '240 x 240 x 2/3600'.
I strip all spaces and stuff out of the string upfront. The numbers can be anything from 1 up to 10000. Been trying, but up to now, I haven't found a solution. Anyone?
KInd regards,
Ton
Snippets of code should be wrapped in
<code> tags not<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).