2

I currently have a Perl script (that I can't edit) that asks the user a few questions, and then prints a generated output to stdout. I want to make another script that calls this script, allows the user to interact with it as normal, and then stores the output from stdout to a variable.

Here's a really simple example of what I'm trying to accomplish:

inner.pl

#!/usr/bin/perl
print "Enter a number:";
$reply = <>;
print "$reply";

outer.sh (based on the answer by Op De Cirkel here)

#!/bin/bash
echo "Calling inner.pl"
exec 5>&1
OUTPUT=$(./inner.pl | tee >(cat - >&5))
echo "Retrieved output: $OUTPUT"

Desired output:

$ ./outer.sh
Calling inner.pl
Enter a number: 7
7
Retrieved output: 7

However, when I try this, the script will output Calling inner.pl before "hanging" without printing anything from inner.sh.

I've found a bit of a workaround by using the script command to store the entire inner.sh exchange to a temporary file, and then using sed and the like to modify it to my needs. But making temporary files for something fairly trivial like that doesn't make a ton of sense (not to mention script likes to add time stamps and \rs to everything). Is there any non-script way to accomplish this?

2
  • your example inner.sh and outer.sh worked perfectly for me ...
    – nabin-info
    Commented Nov 22, 2016 at 22:52
  • Perhaps I over-simplified it then. The original "inner.sh" is actually a Perl script. I don't know anything about Perl, but could that possibly be why my output isn't working? Maybe Perl handles file descriptors and stdout differently? - Just in case, I'll add that detail to my question.
    – spellbee2
    Commented Nov 23, 2016 at 1:15

1 Answer 1

1

The answer is simpler than that. Simply redirect inner's output to a variable with $():

#!/bin/bash
echo "Calling inner.sh"
OUTPUT=$(./inner.sh)
echo "Retrieved output: $OUTPUT"

EDIT:

Now, if there's user interaction with the output in inner.sh (example inner.sh asks user for a number, prints any operation with it and asks the user to input a new value based on that printed result). Then the better is a temporary file like this:

#!/bin/bash
echo "Calling inner.sh"
TMPFILE=`mktemp`
./inner.sh | tee "$TMPFILE"
OUTPUT=$(cat "$TMPFILE")
rm "$TMPFILE"
echo "Retrieved output: $OUTPUT"

Not the answer you're looking for? Browse other questions tagged or ask your own question.