rpaul@hopi.intel.COM (Richard Paul~) (05/22/91)
I want to be able to capture STDERR from an external command and do some substitution and reprint it back out. Following is an experiment I was doing to get this to work. The ls command used is the GNU ls, which with the -h option, prints its options to stderr: #!/stor/gnu/bin/perl open(STDERR, ">&STDOUT"); open(STDOUT); select(STDERR); $| = 1; # make unbuffered open(TMP, "ls -h >&STDERR"); while(<STDOUT>) { s/\+/\%/g; print $_; } close(TMP); close(STDERR); close(STDOUT); The stderr is still going to the tty and not the STDERR filehandle. Is there a way to capture the STDERR output of the TMP filehandle. Any help would be greatly appreciated. I am using the following perl: $RCSfile: perl.c,v $$Revision: 4.0.1.1 $$Date: 91/04/11 17:49:05 $ Patch level: 3 Thanx -- -- ___________________________________________________________________________ | Name: Richard Paul | US-Mail: 5000 W. Chandler Blvd. | | Dept: AME Methodology, SQA | M-stop: CH3-36 | | Group: Arizona Microcomputer Eng. | Chandler AZ, 85226 | | Tel: 602 554 2793, Fax: 602 554 7281 | E-mail: rpaul@sedona.intel.com | | UUCP: decwrl!apple!oliveb!orc!inews!rpaul@sedona.intel.com | | Org: Intel Corporation, ASIC in the Desert, | ---------------------------------------------------------------------------
lwall@jpl-devvax.jpl.nasa.gov (Larry Wall) (05/23/91)
In article <4352@inews.intel.com> rpaul@sedona.intel.com writes: : : I want to be able to capture STDERR from an external command and do some : substitution and reprint it back out. Following is an experiment I was doing : to get this to work. The ls command used is the GNU ls, which with the -h : option, prints its options to stderr: : : #!/stor/gnu/bin/perl : : open(STDERR, ">&STDOUT"); Fine. : open(STDOUT); What's this supposed to do? : select(STDERR); $| = 1; # make unbuffered You mean, make STDERR command buffered. Note that this has no effect on the buffering of subprocesses. : open(TMP, "ls -h >&STDERR"); This is just plain wrong. You're trying to open a file called "ls -h >&STDERR", which I suspect doesn't exist in your current directory. You have to use a vertical bar to indicate a piped command, and even if you do that, the string STDERR will certainly not be recognized by /bin/sh, which only knows about numeric file descriptors. : while(<STDOUT>) Why are you reading from STDOUT? I'd think you'd want to read from TMP. : { : s/\+/\%/g; : print $_; : } : : close(TMP); : close(STDERR); : close(STDOUT); : : The stderr is still going to the tty and not the STDERR filehandle. Is there : a way to capture the STDERR output of the TMP filehandle. You're making this all much too hard. Just say open(TMP, "ls -h 2>&1 |"); while (<TMP>) { tr/+/%/; print; } Larry
ziegast@eng.umd.edu (Eric W. Ziegast) (05/24/91)
(Larry Wall) writes: > You're making this all much too hard. Just say > > open(TMP, "ls -h 2>&1 |"); > while (<TMP>) { > tr/+/%/; > print; > } The above method will merge STDERR into STDOUT. In his book, Larry also shows another way of doing this where STDERR and STDOUT are still handled seperately. # Before your command: redirects STDERR open(SAVEERR, ">&STDERR"); open(STDERR, "> stderr_output_filename"); # Commands you would have used normally # Ex: open(TMP, "ls -h"); #After your command: restores STDERR close STDERR; open(STDERR, ">&SAVEERR"); After this, you can open the file "stderr_output_filename" and read what was sent to STDERR. If you just want to get rid of STDERR, use /dev/null for a filename. The same process would work with STDOUT with a few minor file handle changes. s/ERR/OUT/g +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+ | Eric W. Ziegast Internet: ziegast@eng.umd.edu | | Univ. of Merryland Phonenet: Eric@[301.405.3689] | +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
Tom Christiansen <tchrist@convex.COM> (05/24/91)
And for those who want to read STDERR but send STDOUT to a file (let's call it "kid.out"), do this: open (CMD_ERR, "cmd args 3>kid.out 2>&1 1>&3 3>&- |"); while (<CMD_ERR>) { print "line from stderr: ", $_; } close CMD_ERR; warn "cmd exited $?" if $? >>= 8; open (KID_OUT, "< kit.out") || die "can't open kid.out: $!"; while (<KID_OUT>) { print "line from stdout: ", $_; } Hmm, I just had another odd idea. Let's not use any temp files: open (CMD, "3>&1 (cmd args 2>&1 1>&3 3>&- | sed 's/^/STDERR:/' 3>&-) 3>&- |"); while (<CMD>) { if (s/^STDERR://) { print "line from stderr: ", $_; } else { print "line from stdout: ", $_; } } Now Aren't you glad you had the shell to do that all for you? Of course, you didn't *have* to call sed, or the shell either for that matter. The perl-only solution I leave up as an exercise to the reader, who is presumably less tired and more ambitious than I at 3am. :-) --tom -- Tom Christiansen tchrist@convex.com convex!tchrist "So much mail, so little time."