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.
I come seeking your wisdom once more. Today, the question that I have is a simple matter of loops and how they work when they happen within functions such as grep.
This is my code:
for my $component ( split(/,/, $components_csv) ) {
if (grep { $_ eq $component } @url_components) {
push( @selected_components, $component);
next;
}
# ...
}
In this example, the next keyword: would take me to the next iteration of grep, or to the next iteration of the outer for loop? I could use a label to handle this, but I'm not sure if I need to.
As usual, this is about Someone Else's Code. Not in a blamey way, just that it seems to be my thing to trip over odd cases and bring them out for scrutiny by the good monks. Today I was successful in installing a module published by our good monk cavac, the CPAN module Array::Contains to a Gnu/Linux system, then a few minutes later I went to install it to my cygwin perl setup. I get an error that takes some scrunching up of one's eyes to figure out.
Simplest test case is a one-liner:
$ perl '-Mdiagnostics' -le 'print $diagnostics::VERSION'
couldn't find diagnostic data in /usr/share/perl5/5.40/pods/perldiag.p
+od /usr/share/perl5 /usr/local/lib/perl5/site_perl/5.40/x86_64-cygwin
+-threads /usr/local/share/perl5/site_perl/5.40 /usr/lib/perl5/vendor_
+perl/5.40/x86_64-cygwin-threads /usr/share/perl5/vendor_perl/5.40 /us
+r/lib/perl5/5.40/x86_64-cygwin-threads /usr/share/perl5/5.40 -e at /u
+sr/share/perl5/5.40/diagnostics.pm line 259, <POD_DIAG> line 718.
Compilation failed in require.
BEGIN failed--compilation aborted.
I don't see many modules that use diagnostics so this hasn't come up before for me.
Apr 16, 2025 at 02:05 UTC
A just machine to make big decisions
Programmed by fellows (and gals) with compassion and vision
We'll be clean when their work is done
We'll be eternally free yes, and eternally young Donald Fagen —> I.G.Y. (Slightly modified for inclusiveness)
For several years now, I've used a home made RSS reader to collect and deal with my podcasts. You can see the full code here: github.
I just moved it to a new computer (Ubuntu 24.04, perl 5.38.2; the previous one was Ubuntu 22.04, perl 5.30.0) and suddenly it's failing to be interpret the RSS feeds that are working fine on the old machine.
It's failing on line 277, where it runs parse_string(), which is returning undef instead of the RSS object I get on the old machine, and I cannot work out what might be different to cause this. Any help would be gratefully appreciated.
I want to replace a string with another string which contains (lots of) @, [, ( etc. which have special meaning in Perl and definetely I don't want them to be interpolated.
I can use the q{} function to quote these but how can I call it inside the regular expression, e.g. $xx =~ s/<%xpath%>/\Qq{//div[@id="abc"]}\E/e (does not recognize q{}).
It's late, I'm tired, and I must be missing the obvious. I need another pair of eyes to see what I've overlooked. The code sample below tests a file name against a regex containing the same file name. The first test uses forward slashes (and works as expected). The second test uses backslashes and does not work.
Please note: I have tried escaping the backslashes, but it still fails. I have tried running the regex through the "qr()" function, but it still fails. What am I missing here? TIA for any help you can provide.
#!/usr/bin/perl
use strict;
use warnings;
# WORKS
my $file = 'C:/tmp';
my $regex = 'C:/tmp';
if ($file =~ m/$regex/i) {
print "\nTest with forward slashes -- If stmt is true...\n";
}
# FAILS
$file = 'C:\tmp';
$regex = 'C:\tmp';
if ($file =~ m/$regex/i) {
print "\nTest with backslashes -- If stmt is true...\n";
}
I am not able to find elements in the DOM which are injected dynamically (e.g. via javascript after page load)
These fail: wait_until_visible(xpath=>...) and xpath('...').
<!-- save me as ./content.html -->
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<div id='id1'>element in html</div>
<div id='dynamic-container'></div>
<script>
document.addEventListener("DOMContentLoaded", function(){
setTimeout(function(){
var anElem = document.createElement('span');
anElem.setAttribute("id", "id2");
anElem.innerHTML = "appearing after 1.5s";
document.getElementById('dynamic-container').appendChild(anEle
+m)
},1500);
setTimeout(function(){
var dyn = document.getElementById('id2');
var str = "The dynamic element was "+(dyn==null?"NOT":"")+" fo
+und by getElementById()";
alert(str);
console.log(str);
},2000);
}); // on dom loaded
</script>
</body>
</html>
# it assumes a ./content.html is present on same dir
#!/usr/bin/env perl
use strict;
use warnings;
use WWW::Mechanize::Chrome;
use Log::Log4perl qw(:easy);
use FindBin;
Log::Log4perl->easy_init($ERROR);
my %mech_params = (
headless => 0,
launch_arg => [
'--window-size=600x800',
'--password-store=basic', # do not ask me for stupid chrome ac
+count password
# '--remote-debugging-port=9223',
# '--enable-logging', # see also log above
'--disable-gpu',
'--no-sandbox',
'--ignore-certificate-errors',
'--disable-background-networking',
'--disable-client-side-phishing-detection',
'--disable-component-update',
'--disable-hang-monitor',
'--disable-save-password-bubble',
'--disable-default-apps',
'--disable-infobars',
'--disable-popup-blocking',
],
);
my $mech = WWW::Mechanize::Chrome->new(%mech_params);
$mech->get('file://'.$FindBin::Bin.'/content.html');
my $elem;
$elem = eval { $mech->xpath('//div[@id="id1"]', single=>1) };
die "non-dynamic element not found" unless defined $elem;
$mech->sleep(2);
my $ret = eval { $mech->wait_until_visible(
xpath=>'//div[@id="id2"]',
timeout=>2, # it's already there after 1.5s
); 1;
};
die "dynamic element not found"
unless defined($ret) && ($ret==1) && ! $@;
print "OK dynamic element found!\n";
What I am trying to do is to get notified when a page has finally loaded and settled and when all sort of dynamic HTML elements have been loaded, long after a "DOM-ready" event was fired.
Javascript's getElementById() succeeds. Do I have to poll myself with javascript eval()?
Edit:
I have solved this by following ++LanX's suggestion which is to search/poll HTML elements via javascript. So I am now using something like: do { ($ret, $typ) = $mech->eval($js) } while($ret==0 && !$timeout && $mech->sleep(0.5));. Where $js could be something like this which returns the number of items matched by the specified XPath selector:
Even though I am pretty good at Perl regex, I am learning Perl regex so I can understand the Perl Monks threads on the subject.
I found https://perldoc.perl.org/perlretut entitled perlretut - Perl regular expressions tutorial.
Everything was fine until I came upon this passage in https://perldoc.perl.org/perlretut#Using-character-classes.
(This is a tutorial. It probably belongs in a footnote.)
For natural language processing (so that, for example, apostrophes are
+ included in words), use instead \b{wb}</p>
"don't" =~ / .+? \b{wb} /x; # matches the whole string
I wrote a test to try to understand it. It only caused me more confusion.
use warnings;
use strict;
use feature qw{ say };
if ("don't" =~ / (.+?) (\b{wb}) /x) { # matches the whole string
print "It matches\n";
say $1;
say $2;
}
else {
print "It doesn't match\n";
}
if ("don't" =~ / (.+?) /x) { # It no longer matches the whole string
print "It matches\n";
say $1;
}
else {
print "It doesn't match\n";
}
Output:
It matches
don't
It matches
d
My current company has their entire web application written in Perl using the now defunct CGI modules.
I have been tasked with making a 2 factor authentication system for it, and this defunct CGI module is the bane of my existence. I am doing a simple AJAX call passing JSON data back and forth. The first AJAX call is fine, but the second AJAX call breaks the CGI header data and spits out my raw file path to my Perl login function.
I have been running debugging, and the header type is set properly to application/json, yet it is not getting interpreted properly. If I recall, a Stack Overflow post similar to mine seemed to indicate it is a core CGI header caching issue, but I'm genuinely stumped as to what that means conceptually, and what the working solution is.
I feel like I can't be the only Perl user stuck using defunct modules trying to use AJAX functionality.
My temporary working solution has just been to call a CGI redirect instead of returning the second AJAX response, but this was a horrific band-aid I don't want to keep.
I suppose my questions are, 1) Conceptually what the heck is going on. 2) How can I manually command this CGI module to not short-circuit and respond with what I actually want?
I'm running RHEL9 with perl 5.32. I am trying to get httpd (v2.4.62) to serve some perl scripts through a web browser. When a script is executed that uses Oracle, I get the following error appearing in the httpd/ssl_error_log:
Can't locate loadable object for module DBD::Oracle in @INC (@INC cont
+ains: /usr/local/lib64/perl5/5.32 /usr/local/share/perl5/5.32 /usr/li
+b64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /
+usr/share/perl5)
The Oracle instantclient v11.2 is installed (I need this version for the DB I connect to) and appears to be working properly. sqlplus runs without issues from the CLI. I've also installed the DBI v1.643 perl module from source. If I install DBI through CPAN it installs v1.647, which causes mismatch issues. When I installed DBI the make test passed, so I assume that it installed properly. make install also seemed to work fine.
When it says that it can't locate a loadable object for DBD::Oracle, I'm not sure what it's looking for, so I'm having issues verifying that everything did install as expected.
One thing to note... If I execute the perl script from the CLI as a user, I see the same error. If I execute it as root, it appears to work fine. All the files that I can find appear to have the correct permissions so I don't understand why this is happening.
Can anyone suggest why this is happening and what I should do to resolve this problem?
Thanks!
Update... This doesn't appear to have anything to do with httpd. If I execute the following I can see that root works, but other users do not:
As root there is no error: perl -e 'use DBD::Oracle'
As a user there is an error:
perl -e 'use DBD::Oracle'
Can't locate loadable object for module DBD::Oracle in @INC (@INC cont
+ains: /usr/local/lib64/perl5/5.32 /usr/local/share/perl5/5.32 /usr/li
+b64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /
+usr/share/perl5) at -e line 1.
Compilation failed in require at -e line 1.
BEGIN failed--compilation aborted at -e line 1.