2

I'm having this issue with my perl program that is reading from a file (which I open on STDIN and read each line one at a time using $line = <>). After I execute a `backtick` command, and then I go to read the next line from STDIN, I get an undef, signaling EOF. I isolated it to the backtick command using debugging code as follows:

my $dir = dirname(__FILE__);
say STDERR "before: tell(STDIN)=" . tell(STDIN) . ", eof(STDIN)=" . eof(STDIN);
say STDERR "\@export_info = `echo nostdin | perl $dir/pythonizer_importer.pl $fullfile`;";
@export_info = `echo nostdin | perl $dir/pythonizer_importer.pl $fullfile`;
say STDERR "after:  tell(STDIN)=" . tell(STDIN) . ", eof(STDIN)=" . eof(STDIN);

The output is:

before: tell(STDIN)=15146, eof(STDIN)=
@export_info = `echo nostdin | perl ../pythonizer_importer.pl ./Pscan.pm`;
after:  tell(STDIN)=15146, eof(STDIN)=1

I recently added the echo nostdin | to the perl command which had no effect. How do I run this command and get the STDOUT without messing up my STDIN? BTW, this is all running on Windows. I fire off the main program from a git bash if that matters.

brian d foy
  • 129,424
  • 31
  • 207
  • 592
snoopyjc
  • 621
  • 4
  • 11

1 Answers1

3

Try locally undefining STDIN before running the backticks command, like this example script does. Note that any subroutines called from the sub that calls local will see the new value. You can also do open STDIN, "<", "file for child process to read"; after the local *STDIN but before the backticks but remember to close() the file before restoring STDIN to its old value.

The child process is affecting your STDIN because "the STDIN filehandle used by the command is inherited from Perl's STDIN." – perlop manual

This is just an example; in your actual script, replace the sed command with your actual command to run.

use strict;
use warnings;

#Run a command and get its output
sub get_output {
    # Prevent passing our STDIN to child process
    local *STDIN = undef;

    print "Running sed\n";
    #replace the sed command with the actual command you want to run
    return `sed 's/a/b/'`; 
}

my $output = get_output();
print $output;
#We can still read STDIN even after running a child process
print "Waiting for input\n";
print "Readline is " . scalar readline;

Input:

a
b
c
^D
line

Output:

Running sed
b
b
c
Waiting for input
Readline is line
Nathan Mills
  • 2,243
  • 2
  • 9
  • 15
  • Thanks! Instead I stopped using STDIN and made a different FH called STRIN and changed my <> to instead. – snoopyjc Mar 18 '22 at 10:13