http://qs1969.pair.com?node_id=11137725

viffer has asked for the wisdom of the Perl Monks concerning the following question:

<grovel>Hi wonderful smart people </end grovel>

Hopefully this makes sense
I am processing an afp file
I want to see the value of a certain string so I can use

printf "Triplet_Values = <hex: %*v2.2X>\n", ' ', $data;
The problem is this writes it to stdout

What I want to do is assign it to a variable and write that variable to a log file, or pass that variable back to the calling routine
eg something like

my $variable=printf "--INSIDE Get_Triplet_Values = <hex: %*v2.2X>\n", +' ', $data; print LOG $variable
But all the apostrophes are making it beyond my capabilities.

Any help gratefully received.

Replies are listed 'Best First'.
Re: Assigning printf to a variable
by Athanasius (Archbishop) on Oct 19, 2021 at 14:06 UTC
Re: Assigning printf to a variable
by hippo (Bishop) on Oct 19, 2021 at 14:07 UTC

    It sounds like you want sprintf.


    🦛

Re: Assigning printf to a variable
by Fletch (Bishop) on Oct 20, 2021 at 05:20 UTC

    Just as an aside (very tangentially related), if you've got (say) external code in a module you can't easily change with printfs you need to capture you could always locally set STDOUT to a filehandle opened on a scalar ref.

    #+begin_src perl :results output drawer use strict; use 5.026; my $output; do { open( my $fh, q{>}, \$output ) or die "Problem redirecting to scal +ar: $!\n"; local( *STDOUT ) = $fh; ## pretend this bit is in some 3rd party module you can't modify printf( "This should go %s", qq{elsewhere} ); }; say qq{\$output is '$output'}; #+end_src #+RESULTS: :results: $output is 'This should go elsewhere' :end:

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      local( *STDOUT ) = $fh;

      Or select, though in this example local does have the advantage that it is restored after the block ends.

      But in general, when wanting to capture STDOUT/ERR, I'd recommend Capture::Tiny.

        But in general, when wanting to capture STDOUT/ERR, I'd recommend Capture::Tiny.

        But can Capture::Tiny be used to capture the STDOUT/ERR of the same script that's running?

        Answering my own question, I see the tee and related functions, but that requires that you put the whole script (or at least the parts you want to capture) inside the block that tee is calling. Would there be an equivalent to my Re^2: Errors uncaught by CGI::Carp solution, which captured the STDOUT for the whole script, then did two things with that output during the END (process to one location and dump to the old STDOUT)? Though I guess that use Capture::Tiny; my @capture = tee { ...whole script here... }; process(@capture); isn't that different from BEGIN { duplicate } END { process(...) } ... whole script here .... I guess I'm just trying to see what other ways are possible in the TIMTOWTDI: so would tee {original script contents} be the canonical way with Capture::Tiny, or is there something that involves less wrapping?

        (Sorry for the rambling, self-responding post)

      pryrt very helpfully provided a snippet to redirect STDOUT over on Re^2: Errors uncaught by CGI::Carp

      There, the >& file operator was used. I had come across this before but didn't properly understand it. So I looked it up and thought I understood. But, from my understanding I would have thought that Fletch's example should use open( my $fh, q{>&}, \$output ) or die "Problem redirecting to scalar: $!\n"; instead of the plain q{>}

      What have I missed?

        Thanks for the mention. I'm not an expert on such things; I just learned more about it than I ever thought I would when I was trying to create tests for Games::Literati -- enough that I can muddle through it when I want to do in-memory filehandles and STDOUT duping. But I did have to muddle some before I got that example working.

        Your open( my $fh, q{>&}, \$output ) or die "Problem redirecting to scalar: $!\n"; snippet is combining two concepts: there's the writing to an in-memory filehandle, which is the \$output portion; and there is the "duping" (duplicating) filehandles, which is the q{>&}. You can open a filehandle into the scalar variable like Fletch did without requiring the duping. In Re^2: Errors uncaught by CGI::Carp, I used duping on STDOUT because I had to grab the old version of STDOUT and then replace STDOUT with a new handle. If you look at that code again, you'll see the duping-& was only used on the opens that were dealing with STDOUT, not on the open for the in-memory filehandle. You'll want to keep the two concepts separate in your mind, otherwise you'll make things even more confusing for yourself (and will have a harder time muddling through than I did.)

Re: Assigning printf to a variable
by viffer (Beadle) on Oct 20, 2021 at 04:53 UTC
    Thanks for the replies, sprintf does the trick. Thank you