Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much

Seekers of Perl Wisdom

( [id://479] : superdoc . print w/replies, xml ) Need Help??

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.

Post a new question!

User Questions
3 direct replies — Read more / Contribute
by justin423
on Feb 26, 2024 at 11:42
    This code doesn't work, but I have to think there is an easier way to read a file directory into a database, but I just don't see it.
    my $SQL= "INSERT INTO DIRECTORY_LIST(FILENAME) VALUES ('$filename')"; my $sth= $dbh->prepare($SQL) or die "Prepare".$dbh->errstr; opendir my $dh, $dir or die "Could not open '$dir' for reading: $!\n"; $sth-> execute() or die "".$dbh->errstr; while (my $row = readdir $dh) { if ($filename eq '.' or $filename eq '..'){ next; my ($filename)=($row->[0]); } print "$filename\n"; } print "\n"; closedir $dh; $dbh->disconnect;
Solved- Getopt::Long- Trying to specify "prefix" configuration option produces error
1 direct reply — Read more / Contribute
by parv
on Feb 24, 2024 at 18:24

    I was trying to set prefix option for Getopt::Long but that produces the error message as if that option is unknown or I am doing something wrong (what exactly?) ...

    use v5.32; use warnings; use Getopt::Long; printf qq[Version: perl %s, Getopt::Long %s\n], $^V, $Getopt::Long::VERSION; #use Getopt::Long qw[:config debug prefix - ]; # # Only difference is time, compile or run, of error ... # # Getopt::Long: unknown or erroneous config parameter "prefix" # Getopt::Long::Configure( q[debug], q[prefix], q[-] ); __END__ Version: perl v5.36.3, Getopt::Long 2.52 Getopt::Long: unknown or erroneous config parameter "prefix"

    ... So how do I set the prefix string?

    Got the same error with long_prefix_pattern configuration option. A search brings up issues with user options; did not see anything relevant to module configuration.

    Linked to here on Mastodon.

Enforce single hyphen for single character options in Getopt::Long
3 direct replies — Read more / Contribute
by mrnoname1000
on Feb 24, 2024 at 16:22

    Hiya, Perl newbie here! I've been learning it alongside Ruby with my background consisting of mostly shell, C, and Python (the latter of which takes a wholly different approach to argument parsing).

    As I write more Perl scripts with options, I prefer my option parser to be very strictly configured. My problem is that no matter how I configure Getopt::Long, it always accepts single character options with two preceding dashes. I achieved a compromise when rewriting one of my uglier sh+awk scripts, and here's a stripped down example:

    use Getopt::Long qw( :config posix_default gnu_compat bundling no_auto_abbrev no_ignore_case ); my $column = 1; GetOptions( 'column|c=i' => \$column, ) or die; die if $column < 1;

    I want this program to accept exactly two strings as options, --column and -c, but it also accepts --c. I want the prefix for short options to be - and only -, similar to how -- is treated for long options when bundling is enabled. I had hoped qw( :config prefix_pattern - long_prefix_pattern -- ) would get me what I want, but it seems like the latter isn't processed if the former doesn't match. Anyone know of a clean way to achieve this?

    Also, feel free to suggest improvements or mention best practices! If anyone wants, I can post the full script as well; it's intended to format numbers from stdin/files into human-readable sizes like 681.2K, 12.1M, 3.5G. I should probably figure out my preferred license as well...

Dancer newbie question
4 direct replies — Read more / Contribute
by erickp
on Feb 22, 2024 at 08:29
    Hi guys,

    I'm relatively new to Perl and I'm trying to run a Perl Dancer2 app on my shared hosting (CPanel) environment.

    I tried the little snippet found on metacpan here :

    and it works fine when I curl localhost on port 3000.

    The problem is when I try to execute it from outside, like a normal user would see it at the normal domain URL. It doesn't work.

    I believe this may be a simple matter of a mod_proxy type config in my .htaccess file but I can't figure out how to do this. I do not have access to httpd.conf from Apache as this is a shared host.

    Any ideas on viewing that app from outside?

Not understanding the code to drop privileges in perlsec
7 direct replies — Read more / Contribute
by Nocturnus
on Feb 21, 2024 at 15:56

    Dear seekers of wisdom,

    I have found the following piece of code here:

    0 use English; 1 my @temp = ($EUID, $EGID); 2 my $orig_uid = $UID; 3 my $orig_gid = $GID; 4 $EUID = $UID; 5 $EGID = $GID; 6 # Drop privileges 7 $UID = $orig_uid; 8 $GID = $orig_gid; 9 # Make sure privs are really gone 10 ($EUID, $EGID) = @temp; 11 die "Can't drop privileges" 12 unless $UID == $EUID && $GID eq $EGID;

    I have slightly shortened it and have added line numbers.

    Although I have tried very hard for several hours, I am not able to understand how it works. I believe that I understand it from line 9 on: Obviously, in line 10, we try to gain back EUID and EGID. This should not be possible if we really have dropped privileges. It it was possible, EUID now is different from UID or EGID now is different from GID. That means that if the conditions in line 12 are true the assignment in line 10 has failed, which is what we expect since we have already dropped privileges.

    My main problem are lines 2 and 3 in conjunction with lines 7 and 8. Focusing on the user id only, we here have basically the sequence 2. $orig_UID = $UID followed by 7. $UID = $orig_UID. That does not make any sense IMHO, unless $UID is altered somewhere in between. The only place where this could happen is probably line 4. However, I can't see how the statement $EUID = $UID could alter $UID.

    My tests seem to confirm that point of view. I have made a test environment in Linux (Debian bullseye) where I can run the script setsuid-root or setsuid-other_user, and have inserted print statements after every assignment. Regardless of what my real user id was, and regardless of the setsuid of the script, I never encountered a situation where $UID and $orig_UID were different immediately before executing line 7.

    Please note that I am aware that it is normally not sufficient to set the setuid flag on script files to actually make the script run as the respective user; this is because the interpreter usually does not care about that flag. However, I am using suid-wrapper to run the script setsuid-root or setsuid-other_user.

    So I guess that I'd like to know what the "# Drop privileges" part (lines 7 and 8) actually effect and how they work.

    Thank you very in advance, and best regards ...

Confused by RegEx count
7 direct replies — Read more / Contribute
by Melly
on Feb 20, 2024 at 04:18


    I came across these bits of code on StackOverflow the other day, both of which count the occurrence of a character in a string, and for the life of me, I don't understand what's going on, or why all those steps are necessary:

    If the character is constant, the following is best:
    my $count = $str =~ tr/y//;
    If the character is variable, I'd use the following:
    my $count = length( $str =~ s/[^\Q$char\E]//rg );

    Can anyone help me understand what's going on here?

    map{$a=1-$_/10;map{$d=$a;$e=$b=$_/20-2;map{($d,$e)=(2*$d*$e+$a,$e**2 -$d**2+$b);$c=$d**2+$e**2>4?$d=8:_}1..50;print$c}0..59;print$/}0..20
    Tom Melly, pm (at) cursingmaggot (stop) co (stop) uk
Raku: * v. $_ (asterisk v. the topic variable)
1 direct reply — Read more / Contribute
by 7stud
on Feb 18, 2024 at 14:24

    Dear Monks,

    Here's an example that uses the topic variable $_

    use v6.d; sub go(Int $x where 1 < $_ < 9) { # $_ refers to $x say $x; } go(3); go(0); --output:-- 3 Constraint type check failed in binding to parameter '$x'; expected an +onymous constraint to be met but got Int (0) in sub go at b.raku line 4 in block <unit> at b.raku line 9

    I've also seen examples that use a * instead of $_

    sub go(Int $x where 1 < * < 9) { say $x; } go(3); go(0); --output:-- 3 Constraint type check failed in binding to parameter '$x'; expected an +onymous constraint to be met but got Int (0) in sub go at b.raku line 4 in block <unit> at b.raku line 9

    But * and $_ do not appear to be synonyms because * doesn't work all the time:

    for <a b c> {say $_}; # shorter version: for <a b c> {.say} for <a b c> {say *}; --output:-- a b c * * *

    Here is another example in the docs that uses *:

    sub MAIN( Str $file where *.IO.f = 'file.dat', Int :$length = 24, Bool :$verbose ) { say $length if $length.defined; say $file if $file.defined; say 'Verbosity ', ($verbose ?? 'on' !! 'off'); }

    In that example, I can replace * with $_ or $file, and there is no error, and I get the same output. (I don't understand the where clause because $file.IO.f tests whether $file is a file and returns True or False, so the where clause evaluates to something like True = 'file.dat'. What does that do? Ahh, nevermind: 'file.dat' is the default value, and the parameter variable is $file where $file.IO.f. My tests show that the default value gets assigned to $file before the file test. It would be clearer if you could write  Str $file = 'file.dat' where *.IO.f but that results in an error. )

    Here's an example that calls first() on a list/array, which allows you to look for the first() thing that matches some condition:

    class Foo { method bar( $self: ){ "baz" } }; say Foo.^methods.first(*.name eq 'bar').signature ~~ :($: *%) ; # OUTPUT: «True&#9252;»

    If I replace the * with $_, I get an error.

    I can't find anything in the docs about the use of * in the examples I posted.

is CPAN::WAIT dead?
3 direct replies — Read more / Contribute
by pope-indigent
on Feb 18, 2024 at 12:49
    Hey, CPAN suggested that I install the CPAN::WAIT module, but the tests are failing, in part I think because "" seems to have a bug; the bug is, it doesn't exist.

    So I'm wondering if WAIT is a dead horse, or if it would be worth bringing up a WAIT server on my Church's little dev box and hitting that. Or perhaps somebody already did that, and the CPAN::WAIT docs and tests could be updated.

    the WAIT module also fails to install under CPAN, and I"m not sure why ... could be the same problem. Or not.

    Before I burn a lot of time, I thought I should seek the wisdom of more enlightened souls.

    If I do bring up such a thing, and people so desire, I may make it public.

    Handers try to be helpful, and might even do so without a profit motive, if we can't find a way to profit, at least. (

Faster of two options for finding keywords in a database
6 direct replies — Read more / Contribute
by cormanaz
on Feb 17, 2024 at 10:45
    Good day monks. I have text stored in a postgres database. For each record, I also have a JSONB column containing a hash of keywords previously found in the text. I want to count the number of a particular subset of keywords in each record. My question is whether it is faster to do it using option 1:
    my @kwlist = qw(foo bar baz qux); my $kwre = join('|',@kwlist); my @items = getfromdb("select id,text from table"); # I have a sub tha +t does this foreach my $i (0..$#items) { my ($id,$text) = @{$items[$i]}; my $count = 0; while($text =~ /$kwre/g) { $count++; } }
    or using option 2:
    use JSON::XS; my @kwlist = qw(foo bar baz qux); my @items = getfromdb("select id,keywordhash from table"); # I have a +sub that does this foreach my $i (0..$#items) { my ($id,$temp) = @{$items[$i]}; my $kws = decode_json($temp); my $count = 0; foreach my $k (@kwlist) { if (defined($kws->{$k})) { $count++; } } }
    Or is there some faster way to do it I haven't thought of? I have no idea what is going on under the hood in these two options that would affect execution time but I feel confident some other monks do.

    BTW I realize there may be some way to do it with an exotic postgres query, but it's beyond me and anyway the list of keywords I'm looking for is rather long so it would be unwieldy.

mysql error
2 direct replies — Read more / Contribute
by dcscott
on Feb 16, 2024 at 12:06

    If I try to run a script from a login I get this response even though DBD::mysql exists on every path in the error:

    Opening the database
    install_driver(mysql) failed: Can't locate loadable object for module DBD::mysql in @INC (@INC contains: . /usr/local/lib/perl5/site_perl/5.38.2/x86_64-linux /usr/local/lib/perl5/site_perl/5.38.2 /usr/local/lib/perl5/5.38.2/x86_64-linux /usr/local/lib/perl5/5.38.2) at (eval 6) line 3. Compilation failed in require at (eval 6) line 3. Perhaps a module that DBD::mysql requires hasn't been fully installed

    HOWEVER.... I can run it in my browser with no errors

    Why is this??

Add your question
Your question:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":

  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • 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).
  • Want more info? How to link or How to display code and escape characters are good places to start.