http://www.perlmonks.org?node_id=479

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
use PDF::API2 to add pdf bookmark
1 direct reply — Read more / Contribute
by vincentaxhe
on Jun 16, 2024 at 06:28
    I write a perl script to add bookmarks to pdf as below
    #!/bin/perl # add bookmark to pdf, at most two levels use strict; use PDF::Reuse; use File::Basename; my ($oldfile, $toc, $gap) = @ARGV; my $newfile = basename($oldfile, '.pdf') . '_new.pdf'; our $lastpage = 0; sub insertbookmark(@){ my ($chapter, @section) = @_ or return; my %items = (text => $chapter->{text}, act => $chapter->{act} ); @items{'close', 'kids'} = (1, \@section) if @section; prBookmark(\%items); } sub valid($){ my $line = shift; my ($text, $page) = $line =~ /^(.+)\t(\d+)$/ or die $line, 'is ill + formatted'; # ()have to escape $text =~ s/([()])/\\\1/g; warn $text, ' on page ', $page, ' must be wrong' if $page < $lastp +age; $lastpage = $page; return ($text, $page); } prFile($newfile); prDoc($oldfile) or die; open my $fh, '<', $toc or die; my @section; while (<$fh>){ chomp; my $flag = s/^\t//;# at most one tab my ($text, $page) = valid $_; $page += ($gap - 1); my $bookmark = { text => $text, act => "$page, 40, 700"}; unless ($flag){ insertbookmark @section; @section = (); } push @section, $bookmark; } insertbookmark @section; prEnd();
    Lately I try use pdftk xxx.pdf dump_data_utf8 and to do some modification but I found the bookmarks are not encoded well, if I open with firefox or evince, the bookmarks of chinese characters are a mess, pdfs show fine only with zathura. I ask around, the given advice is to use PDF::API2 to do the work, but I can only add bookmarks to an bookmark-empty pdf as below, but the bookmark is well-encoded, show chinese characters well with firefox or evince.
    use PDF::API2; use utf8::all; use File::Basename; my $oldfile = shift; my $newfile = basename($oldfile, '.pdf') . '_new.pdf'; my $pdf = PDF::API2->open($oldfile); my $item = $outline->outline(); $item->title('some chinese characters'); $item->destination($pdf->open_page(1)); $pdf->save($newfile);
    I cannot add bookmarks to a pdf if It already has bookmarks, nor can I delete all bookmarks.
    # perl bookmark writeruse PDF::API2; use PDF::API2; use utf8::all; use File::Basename; my $oldfile = shift; my $newfile = basename($oldfile, '.pdf') . '_new.pdf'; my $pdf = PDF::API2->open($oldfile); my $outline = $pdf->outline(); while (my $item = $outline->next()) { $item->delete(); print $i++, "\n"; } $pdf->save($newfile);
    I cannot see what PDF::API2 try to tell me the right way to do modification
Text::ExtractWords exhibits incomprehensible behavior?
3 direct replies — Read more / Contribute
by ibm1620
on Jun 15, 2024 at 11:42
    Hello, Monks,

    I'm looking for a module to extract words from a stream of text. I installed Text::ExtractWords and tried it:

    #!/usr/bin/env perl use v5.38; use Text::ExtractWords qw(words_list); say $^V; my $text = "12/21/84 Bob's 21st b'day was a wine-and-dine."; say $text; my @list; words_list(\@list, $text, {minwordlen => 2, maxwordlen => 26 }); say "Found words: " . join ' ', map {"[$_]"} @list; say $text;
    v5.38.2 12/21/84 Bob's 21st b'day was a wine-and-dine. Found words: [12] [21] [84] [bob's] [21st] [b'day] [was] [a] [wine-and +-dine] 122184bob's21stb'daywasawine-and-dine
    Note the output value of $text after call. How is it possible for any subroutine to modify a parameter, since I don't pass in a reference?

    Moreover, I looked at Text::ExtractWords.pm and it's all basically boilerplate except maybe for one line, which I don't understand:

    bootstrap Text::ExtractWords $VERSION;
    I feel like I'm missing something obvious here...

    Update: I'm not able to step into words_list() using the debugger! It just proceeds to my next source line.

    Update2: I even tried making a copy of $text (my $copy = $text) and passing $copy to words_list(), and afterwards *both* $copy and $text were munged. As Danny mentions below, this is XS code.

Error at during DATA / Email::Sender::Transport::SMTP
2 direct replies — Read more / Contribute
by talexb
on Jun 14, 2024 at 10:16

    I'm getting this error when trying to send an E-Mail using sendmail ..

      Email::Sender::Transport::SMTP::_throw('Email::Sender::Transport::SMTP +=HASH(0x564b90f0b378)', 'error at during DATA', 'Net::SMTP::_SSL=GLOB +(0x564b8e0b7f10)') called at /usr/local/share/perl/5.34.0/Email/Sende +r/Transport/SMTP.pm line 270
    I'm a little puzzled, because I send other, similar messages using this module, and they all work fine. My only hypothesis is that the message might be too large for Outlook to handle. I see that there's a _hunk_size hard-coded to 2**20, and wonder if I could try reducing that hunk size to get this through.

    Alex / talexb / Toronto

    Thanks PJ. We owe you so much. Groklaw -- RIP -- 2003 to 2013.

catch "use Inline::C" death
3 direct replies — Read more / Contribute
by bliako
on Jun 14, 2024 at 05:36

    I have a test which must fail as it tests passing bogus CFLAGS to Inline::C. e.g.

    use Inline C => Config => ccflagsex => '-test-bliako-A', ; ... use Inline C => <<'EOC'; #include <stdio.h> ... EOC

    The problem is that passing bogus CFLAGS to use Inline C => Config ... dies and my test fails without getting the chance to recognise that actually the test was passed as the die was expected.

    I tried to enclose said codeblock in eval { }; but I see no difference. Test fails.

    I find Inline::C using the use Inline C ... impractical and unecessary (perhaps it comes from Inline). So, is there a way to separate use Inline C; from its Config and Code sections? Ideally:

    use Inline C; Inline::C::config(...); Inline::C::embed_C_code(... c code ...);

    Alternatively, how can I catch the croak's and die's from when use'ing a module with Test::More.

    Or perhaps using require ... ?

    ps. I also tried to enclose it in a try{}catch{}; with same result: death

    bw, bliako

updating Devel::BeginLift (or, statement vs. expression keywords)
1 direct reply — Read more / Contribute
by prj
on Jun 13, 2024 at 17:17
    I have a lot of code that uses Sub::Curried, which implements a "curry" keyword. Since it predates the custom keyword feature added in Perl 5.12, it uses Devel::Declare and Devel::BeginLift. But Devel::BeginLift uses some Perl internals in its XS code and doesn't build with recent versions. I made some changes based on total guesswork and got it to compile, but it doesn't pass its tests. Are there any guides to working with opcodes? As another approach, I also tried starting from scratch with Keyword::Simple, Keyword::Declare, or Keyword::Pluggable. But ::Simple and ::Declare can only implement statement-like keywords, while the "curry" keyword is supposed to be like "sub": it's used as a statement in the case of a named sub, or as an expression for an anonymous sub. Keyword::Pluggable can define expression-like keywords, but it expects any particular keyword to be always expression-like or always statement-like. It can't handle one keyword used both ways. Are there other modules that can define keywords with this flexibility?
Compile perl with custom compiler path, perlbrew solution preferred
1 direct reply — Read more / Contribute
by bliako
on Jun 13, 2024 at 11:05

    Dear Monkees!

    I need to compile perl from source with custom compiler living in /usr/local/gcc82 (with subdirs bin, include, lib etc.). The reason is that I am embedding CUDA code (which is C) via Inline::C which needs this specific compiler. And XS code must be compiled with same compiler as its perl. (Indeed I get segmentation fault when doing otherwise). So I need perl compiled with this specific compiler and I am doing this on Linux.

    I prefer to let perlbrew do the compilation and installation. Is there a simple way to do it? Alternatively, I need to do it manually.

SOLVED: Get a list attributes from a given tag in Mojo::DOM
1 direct reply — Read more / Contribute
by igoryonya
on Jun 13, 2024 at 06:31
    I am learning a Mojo::UserAgent module and I've stumbled upon an issue, that I can't find an answer to on the internet and Mojo's mans.

    Here is the test code:

    #!/usr/bin/env perl use utf8; use feature 'say'; use Mojo::UserAgent; my $data = undef; #Get correct file my $cache = shift // '/tmp/cache.html'; if(-d $cache){ die("'$cache' is folder. You need to use file."); } if(-e $cache){ $data = Mojo::File->new($cache)->slurp; }else{ say 'Fetching fresh HTML'; my $ua = Mojo::UserAgent->new; my $tx = $ua->get('https://www.mojolicious.org'); die "Could not fetch! Error is ", $tx->result->code unless($tx->re +sult->is_success); $tx->result->content->asset->move_to($cache); $data = $tx->result->body; #->body is not only <body>...</body> +, but a complete loaded resource content for 1 file. } say "Tags are:\n\t", Mojo::DOM->new($data)->find('a')->map(attr=>'href +')->uniq->sort->join("\n\t");
    It works, but, is there a way to list the existing attributes from a given tag?
    I tried to find it out from Mojo:
    :DOM
    :Asset
    :Content
    and I didn't find any mentioning of attr enumeration or conversion to string.
    Is there a way to find out what tags exist on found tag?

    Something like this, probably?:

    Mojo::DOM->new($data)->find('a')->map(attr=>'*')->join("\n\t");
    I tried to enumerate with:
    my %attrs = "Tags are:\n\t", Mojo::DOM->new($data)->attr; map{ print "(%s)/(%s)\n", $_, $attrs{$_} } sort keys %attrs;
    But I only got empty hash.

    UPDATE

    OK, i've figured it out:
    my $dom = Mojo::DOM->new($data); map{ say } $dom->find('a')->first; my $attrs = $dom->find('a')->first->attr; map{ printf "(%s)/(%s)\n", $_, $attrs->{$_} } sort keys %$attrs;
Defined test creates non-empty hash value
2 direct replies — Read more / Contribute
by glendeni
on Jun 12, 2024 at 12:34

    I'd always assumed tests could never _create_ anything - they were just tests that either succeeded or failed, never actually affecting variables solely by being used. So was very surprised to recently find that use of the 'defined' test on a hash of arrays ala

    defined $hash{$name}[$integer]

    actually _created_ an empty $hash{$name} if $hash{$name} is non-existent, so is thereafter not non-existent.

    Example code:

    my %hash = ( "A" => [ 1,2 ] ) ; if ( exists $hash{"B"} ) { say "This will NOT print" ; } if ( defined $hash{"B"}[1] ) { say "This will NOT print" ; } if ( exists $hash{"B"} ) { say "This WILL print" ; }

    So the "correct" test for existence of an array element in a hash of arrays should be

    if ( exists $hash{"B"} && defined $hash{"B"}[1] )

    Would appreciate comments by those with deeper knowledge of perl than I, since I can't see how such creation is in any way beneficial - rather it can introduce problems into a script, since the first use of such a test will fail but a second same test will later succeed without the programmer intending (or expecting) any such change.

    IMHO a test should succed, or fail, or throw an error - period.

    FYI the same occurs for a test ala "$#{$hash{"B"}} > -1".

    Background: Have used perl regularly since 1998 so am experienced in perl, but never dug too deeply into it.

uninitialized value
4 direct replies — Read more / Contribute
by frank1
on Jun 12, 2024 at 04:41

    Am trying to get button to do something, and its working well.

    But how can i get rid of this error

    Use of uninitialized value in string eq at jj.pl

    if (param('btn') eq 'btn') { #Do something }
    <button type="submit" name="btn" value="btn">Do something</button>
Perl and Mysql Queries
3 direct replies — Read more / Contribute
by Milti
on Jun 10, 2024 at 13:13

    I am using Mysql 8.4 and am trying to use a form to provide info to a Perl cgi to insert data into a Mysql database table. Previous I used Mysql 5.7 and was successful with these statements:

    use DBI; print "Content-type: text/html\n\n"; use POSIX qw(strftime); $shortdate = strftime "%B %d, %Y", localtime; $Posted=$shortdate; $JobID=param('JobID'); $EmployerID=param('EmployerID'); $EmployerName=param('EmployerName'); $Title=param('Title'); $City=param('City'); $StateProvince=param('StateProvince'); $Description=param('Description'); $Function=param('Function'); $Sector=param('Sector'); $Country=param('Country'); my $dbh = DBI->connect('dbi:mysql:jobs_db','poster','posterpasswd'); my $sth =$dbh->prepare("INSERT INTO jobs (JobID,EmployerID,EmployerNam +e,Title,City,StateProvince,Description,Function,Sector,Country,Posted +) Values(?,?,?,?,?,?,?,?,?,?,?)"); $sth ->execute($JobID,$EmployerID,$EmployerName,$Title,$City,$StatePro +vince,$Description,$Function,$Sector,$Country,$Posted);
    Everything worked! Now it doesn't work. I have gotten an error message noting syntax error near my $sth=$dbh->prepare and another one indicating the use of place holders has been deprecated and cannot be used. I'm at a lost for ideas. Can anyone provide the currently acceptable way to use Perl statements to insert the data into the table? I would truly appreciate any help offered.


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