Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

The Monastery Gates

( #131=superdoc: print w/replies, xml ) Need Help??

If you're new here please read PerlMonks FAQ
and Create a new user.

poll ideas quest 2021
Starts at: Jan 01, 2021 at 00:00
Ends at: Dec 31, 2021 at 23:59
Current Status: Active
5 replies by pollsters
    First, read How do I create a Poll?. Then suggest your poll here. Complete ideas are more likely to be used.

    Note that links may be used in choices but not in the title.

Perl News
Perl/Raku community involvement survey
on Jul 16, 2021 at 13:53
1 reply by jdporter

    Episodic Volunteering in Free/Libre/Open Source (FLOSS) Communities - a survey by kudra

    TPF announcement

    ... research to understand episodic, or occasional, participation in the Perl and Raku communities... The results of the research will be provided as a TPF report and will assist the community in improving practices for managing episodic participation to provide insights into what FLOSS projects could do to become more sustainable.
Net::Clacks Important data corruption bugfix released
on Jul 07, 2021 at 03:39
2 replies by cavac

    I usually try to avoid clobbering the PM News section with release information about my modules. But i found a problem in my Net::Clacks::Server which can, under the wrong circumstances, either prevent startup or lead to all sorts of data corruption in cached data.

    I have fixed this in Version 18 (at least i think it is completely fixed, bug reports are welcome).

    Unfortunately, this upgrade features an incompatible change that clobbers the persistance file. There is a workaround for that to keep your cached data, though. From the UpgradeGuide.pod:

    WARNING: BREAKING CHANGES regarding persistance files.
    Version 18 provides better reliability for the Clacks Server when using a persistance file, including startup problems and prevention of data loss.
    Here is the problem in older versions: If the server process is killed while writing the persistance file, the file on disk may be invalid (partial data) or completely blank. Blank files at least prevented the server from starting up, but otherwise incomplete files could lead to data corruption in cached data and/or all other sorts of problems. This relates to the fact that the server only does very minimal checks on its internal cache during runtime for performance reasons. The original persistance file was just a quick hack to dump/restore the cache between runs and did not account for system crashes or the process being killed while writing to disk.
    This new version of Net::Clacks::Server tackles this in in a multi-stage approach:
    1.) The persistance file now includes the ENDBYTE string as a third line. This is used to check if the file is complete.
    2.) Before overwriting the current persistance file, it is COPIED to a file with '_bck' added to the configured name.
    3.) The file is written under a new name (with '_' added at the end) and then MOVED over the correct file name. File move (rename) within the same directory should be an atomic operation of the operating system, so it either works or doesn't (no stopping half-way inbetween).
    4.) An invalid persistance file doesn't prevent the clacks server startup. If it detects an invalid file, it first tries to load the previous version ('_bck'), then as a last desperate measure to prevent data loss, it tries to load the temporary file ('_'). If that also fails, it starts 'blankety-blank'.
    Clacks caching was always designed as a CACHE, not as the final storage for important data. This upgrade to Version 18 changes the file format of the persistance file slighty. The older format is now detected as invalid, resulting in a "blankety-blank" startup. If you really want or need (?!?!?!) to preserve the cached data for some reason, there are two ways to accomplish this:
    1.) Stop the clacks server and upgrade the Net::Clacks package. Edit the persistance file and add a third line with the word "ENDBYTES" without quotes as its only content.
    2.) If you are running a master/slave setup with interclacks, you can stop ONLY the server that has the persistance file. Then upgrade Net::Clacks and start the server. It should start "blankety-blank" and automatically resyncronize cached data from the interclacks network. It works the same if all your clacks servers use persistance files for some weird reason, just restart them one-by-one, waiting inbetween for the interclacks sync to finish. You can use the example Connect to the server you keep running and start the MONITOR command. While interclacks sync is in progress, you will see KEYSYNC commands flying between the servers. If you stop seeing them for a few seconds, KEYSYNC is finished.

    perl -e 'use Crypt::Digest::SHA256 qw[sha256_hex]; print substr(sha256_hex("the Answer To Life, The Universe And Everything"), 6, 2), "\n";'
Generate a thumbnail for a given link
2 direct replies — Read more / Contribute
by Matthew.S
on Jul 25, 2021 at 10:31
    Hello Perl Monks. I'm looking to write a Perl utility that will accept a link to some web page/resource and will generate a thumbnail for that web page (assuming that the given web page/resource supports it). When saying "thumbnail" I expect to generate something like say WhatsApp generates when You paste a link into it (a picture with some short text title and a link). The desired output from the utility could be an image file and a textual title in a text file that I can later use to my needs. What general approach would You suggest for me to take? Thank You for Your wisdom.
file modifications using file::find
4 direct replies — Read more / Contribute
by propellerhat
on Jul 24, 2021 at 21:59
    After much searching and reading, the articles I have have found regarding File::Find do nothing other than list file names, though they begin by saying things such as "do something with file". I need help or a tutorial which shows me how to: (1) run an IF check on files located by File::Find (2) read from and write to a file which passes the IF check I suppose File::Find returns whatever I need to open a filehandle, but I have not located the File::Find specification.
Inline::C : passing parameters to functions, modifying by reference
5 direct replies — Read more / Contribute
by bliako
on Jul 22, 2021 at 19:54

    Dear Monks,

    I have spent quite some time in trying to do a seemingly simple task with Inline::C, that of passing a reference to a function and the function modifying it so that caller gets results back. I don't want to use the return() mechanism, so my function looks like int func(SV *inp, SV *out); inp is a readonly ref and out is the ref I would like to write to.

    I have 3 cases I would like to deal with:

    1. out is an arrayref, e.g. my @inp; my @out; func(\@inp, \@out); In this case I want to remove all elements of @out if any and then make it a 2D array of 5cols and 3rows, containing the number 42.

    2. out is a scalar, e.g. my @inp; my $out; func(\@inp, $out); In this case I want to make $out an arrayref and proceed to fill it as above, so that caller can dereference as my @out = @$out.

    3. out is a scalarref, e.g. my @inp; my $out; func(\@inp, \$out); In this case I want to find if its dereference, e.g. $out is a ref to any array or hash, or just a plain scalar. If it's a plain scalar I would like to make it an arrayref and proceed as above, so that caller can dereference as my @out = @$out.

    Can anyone help me to fill any of the blanks in this advent calendar of perlguts?

    Here is a test script testing each case.

    use strict; use warnings; use Test::More; use Inline C => Config => BUILD_NOISY => 1, clean_after_build => 0, warnings => 10, ; use Inline C => <<'EOC'; #include <stdio.h> // checks if array is indeed an arrayref and sets array_sz to its size + and // returns 1 else returns 0 (not an array) int is_array_ref( SV *array, size_t *array_sz ){ if( ! SvROK(array) ){ fprintf(stderr, "is_array_ref() : warning, i +nput '%p' is not a reference.\n", array); return 0; } if( SvTYPE(SvRV(array)) != SVt_PVAV ){ fprintf(stderr, "is_array_r +ef() : warning, input ref '%p' is not an ARRAY reference.\n", array); + return 0; } // it's an array, cast it to AV to get its len via av_len(); // yes, av_len needs to be bumped up, it's $#array int asz = 1+av_len((AV *)SvRV(array)); if( asz < 0 ){ fprintf(stderr, "is_array_ref() : error, input arra +y ref '%p' has negative size!\n", array); return 0; } *array_sz = (size_t )asz; return 1; // success, it is an array and size returned by ref, abo +ve } int func( SV *inp, SV *out ){ AV *av, *av2; size_t i, j, asz; if( is_array_ref(out, &asz) ){ printf("Case1: @out\n"); // we have an \@R, e.g. func(\@R) av = (AV *)SvRV(out); // but first clear any contents if( asz > 0 ) av_clear(av); } else if( SvROK(out) ){ printf("Case3: \\$out\n"); // we have a scalar ref, e.g. func(\$x) av = newAV(); sv_setsv(SvRV(out), (SV *)av); } else { printf("Case2: $out\n"); // we have a scalar e.g func($x); av = newAV(); sv_setsv(out, (SV *)av); } // and fill it in for(i=0;i<5;i++){ av2 = newAV(); av_extend(av2, 3); av_push(av, (SV *)av2); for(j=0;j<3;j++){ av_store(av2, j, newSViv(42)); } } return 0; // success } EOC my @inp = (1..5); my @out; my $T = 'Case1'; is(func(\@inp, \@out),0, "$T: called success."); is(scalar(@out), 5, "$T: rows are 5"); for(my $i=0;$i<5;$i++){ ok(ref($out[$i])eq'ARRAY', "$T : item $i is ARRAYref."); is(scalar($out[$i]), 3, "$T : it has 3 elements."); for(my $j=0;$j<3;$j++){ is($out[$i]->[$j], 42, "$T : it's value is 42."); } } $T = 'Case2'; my $out; is(func(\@inp, $out),0, "$T: called success."); is(ref($out)eq'ARRAY', "$T: it is now an ARRAYref."); @out = @$out; is(scalar(@out), 5, "$T: rows are 5"); for(my $i=0;$i<5;$i++){ ok(ref($out[$i])eq'ARRAY', "$T : item $i is ARRAYref."); is(scalar($out[$i]), 3, "$T : it has 3 elements."); for(my $j=0;$j<3;$j++){ is($out[$i]->[$j], 42, "$T : it's value is 42."); } } $T = 'Case3'; $out = undef; is(func(\@inp, \$out),0, "$T: called success."); is(ref($out)eq'ARRAY', "$T: it is now an ARRAYref."); @out = @$out; is(scalar(@out), 5, "$T: rows are 5"); for(my $i=0;$i<5;$i++){ ok(ref($out[$i])eq'ARRAY', "$T : item $i is ARRAYref."); is(scalar($out[$i]), 3, "$T : it has 3 elements."); for(my $j=0;$j<3;$j++){ is($out[$i]->[$j], 42, "$T : it's value is 42."); } } done_testing();

    thanks in advance, bw, bliako

How Perl decides where a variable ends and text starts: Match variables in string interpolation
1 direct reply — Read more / Contribute
by davido
on Jul 22, 2021 at 18:14

    Once in awhile Perl still surprises me.

    This code is obviously broken:

    my ($left, $right) = qw(abc def); print "$left_$right\n";

    The problem is that interpolation causes Perl to want to print a variable $left_ and $right, but we declared $left and $right. There are several ways to fix this, two of which are:

    print "$left\_$right\n"; print "${left}$right\n";

    ...and of course you could just use the concatenation operator, but then I wouldn't have anything to puzzle over.

    But observe the following:

    my $string = "abcd"; if ($string =~ m/(ab)(cd)/) { print "$1_$2\n"; }

    The output is ab_cd. So in this case Perl automatically treated that interpolation as "${1}_$2\n" without me telling it to do so. I've looked over The Gory details of parsing quoted constructs and haven't found an explanation. I assume that in the case of numbered regex variables, Perl decides that if the variable starts with a numeric digit, the identifier must end when there are no more numeric digits. Is this behavior reliable? Is it documented? Is it likely to ever change?

    I'm asking because I found it in a code review and was sure it was broken until we talked it over and tested to verify the behavior was to parse "$1_$2\n" as $1 . '_' . $2 . "\n" even though we would prefer to disambiguate using \ or ${n}.

    Update: I do see in perldata: Identifier-parsing:

    Meanwhile, special identifiers don't follow the above rules; For the most part, all of the identifiers in this category have a special meaning given by Perl. Because they have special parsing rules, these generally can't be fully-qualified. They come in six forms (but don't use forms 5 and 6):

    1. A sigil, followed solely by digits matching \p{POSIX_Digit}, like $0, $1, or $10000.

    I don't know that this is worded quite right, because $1_ could be construed as NOT being an identifier consisting solely of digits. But it's the closest thing I can find to an explanation. But I'll take that as answering my own question: Yes, it's intentional and documented behavior.


Question regarding a regex
7 direct replies — Read more / Contribute
by CrashBlossom
on Jul 22, 2021 at 14:34
    Hello Monks,
    I would like some help in understanding the regular expression in the following code:
    sub TextFile { return 0 if (! -f $_[0]); return 0 if (! -r $_[0]); open FH, "<" . $_[0]; my $block = " " x 4096; my $bytesread = sysread FH, $block, 4096; close FH; if (! defined $bytesread) { print "*** ERROR: TextFile: $_[0]: $!\n"; return 0; } return $block =~ /^[\r\n\t -~]*$/s; }
    It attempts to guess whether a file is a text file based on what it sees in the first 4096 characters. I ran across it while seeking an alternative to -T to check for a text file. It seems to work in my tests, but I don't understand why because I don't understand what the regex is matching.

    My understanding is that [] defines a character class. A ^ before [] means negation. * means zero or more. $ means end of line. So if I put that all together, it seems to mean that
    $block =~ /^[\r\n\t -~]*$/s
    is true if $block does nor include any of \r\n\t -~ before an end of line. But that doesn't make sense. I'm also mystified by the inclusion of the characters -~ in the character class.

    Can anyone unpack all this for me?

    I am running strawberry perl 5.30 on windows 10.

Perl treats period as space in string
5 direct replies — Read more / Contribute
by htmanning
on Jul 20, 2021 at 16:03

    I have a database of phrases that I'm checking a string against. Perl recognizes all periods as spaces even if I don't want it to. What is the workaround for this?

    $phrase = ""; if ($string =~ m/$phrase/i){
    The above recognizes "" and "club market" but I only want to recognize the one with the period. What am I missing?
Cool Uses for Perl
Linux/Perl Cabrillo to ADIF Conversion Script
No replies — Read more | Post response
by jmlynesjr
on Jul 21, 2021 at 16:15

    Script to convert an Amateur Radio Cabrillo format log file into to an ADIF(Amateur Data Interchange Format) logfile.

    A Cabrillo file has space delimited fields. An ADIF file has tag delimited fields and field order is not important. A Cabrillo file is used for entry into Ham radio contests like the ARRL Field Day. ADIF files are used to import contact data into logging software like This process was used to create(with a Cabrillo log of 200+ entries and then import this file into my log on I prefer to log on paper and I will use this process to enter and import contact data as I fill a log sheet.

    Posted here so it can be found by the search engines. Other utilities that I have found are for Windows only.


    There's never enough time to do it right, but always enough time to do it over...

Linux/Perl Cabrillo Logfile Creation Script
No replies — Read more | Post response
by jmlynesjr
on Jul 21, 2021 at 16:12

    Script to create a simple Amateur Radio Cabrillo Format Log File

    Not much out there for Linux users, had to roll my own. Log file created with 200+ entries then converted to ADIF format and uploaded to Posted here so it can be found by the search engines.


    There's never enough time to do it right, but always enough time to do it over...

Log In?

What's my password?
Create A New User
Domain Nodelet?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (3)
As of 2021-07-27 05:53 GMT
Find Nodes?
    Voting Booth?

    No recent polls found