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

I have a shell script from which I execute a block of perl code. In that Perl block, I set a variable that I need to access back at the shell script. Here is a simplified example. It doesn't make much sense of course, but for the sake of the example it should be good I hope:
#!/bin/sh str = "Hello" perl - $str << 'EOF' $str2 = shift; $str3 = "world"; print "$str2 $str3\n"; EOF ##here, back in the shell, I need to access $str3. ##Any idea how to do this? Thank you.

Replies are listed 'Best First'.
Re: pass perl variable to shell script
by GrandFather (Saint) on Aug 10, 2010 at 21:24 UTC

    Turn the problem inside out. Instead of using Perl within you shell script, use OS tools from within Perl. That is, replace the shell script with a Perl script.

    True laziness is hard work
      Thank you, GrandFather. I can't replace shell with Perl. That's the constraint I have. I must use existing shell script and add a block of Perl code in it.
Re: pass perl variable to shell script
by oko1 (Deacon) on Aug 10, 2010 at 22:26 UTC

    Not Perl, but - use command substitution.

    #!/bin/sh str="Hello" out=$(perl - $str << 'EOF' $str2 = shift; $str3 = "world"; print "$str2 $str3\n"; EOF ) str3=$(echo $out|cut -d' ' -f2) echo $out echo "In the shell, \$str3 is '$str3'"

    --
    "Language shapes the way we think, and determines what we can think about."
    -- B. L. Whorf
      Thank you, okol. I like the simplicity of your suggestion, but it doesn't work the way you showed it (I added the 3 lines you mentioned right after the last EOF (curly bracket seems unnecessary) and it gave me syntax error at the str3=$... line). However, even if it did work, I would like something more generic and not code dependent: if I remove 'print' statement from the perl block, your 'str3=' line would fail.
        it doesn't work the way you showed it (I added the 3 lines you mentioned right after the last EOF (curly bracket seems unnecessary) and it gave me syntax error at the str3=$... line).

        Um. "I did it differently from way you showed it, and it doesn't work."

        Why am I not surprised? Why are you surprised?

        The "curly bracket" (the parenthesis, actually) closes the opening parenthesis on the 'perl' line, and is indeed necessary - at least if you want the script that I wrote to work.

        The core of your question seems to be "can I set a variable in Perl and read it from the shell". The answer is no, you cannot: the Perl instance that you're launching is a child process of the shell. Any variable it sets disappears when the child process exits. The only way to keep the content of that variable is to either save it in some external resource (e.g., a file) or to make it part of the output from the Perl process and capture that output in the shell. The mechanism for doing the latter is called "command substitution" - which my script demonstrates.

        One possible (and possibly fraught) exception is if the value that you're trying to pass is a number, 0-255. You could then use that value as the exit status of your script, and read that status via the '$?' variable in the shell. Although this is usable, and in fact used by some standard programs (e.g., "mail"), it's not recommended; that exit flag is normally used to determine whether a program succeeded or failed.


        --
        "Language shapes the way we think, and determines what we can think about."
        -- B. L. Whorf
Re: pass perl variable to shell script
by rovf (Priest) on Aug 11, 2010 at 09:25 UTC
    You could write your variables into a file and evaluate the file afterwards.

    Or if you don't need the stdout of your program for an other purpose, write to stdout the value of the variable in the syntax of shell assignment, and use "eval" on the output of your Perl program, i.e. something like

    eval `perl .....`

    -- 
    Ronald Fischer <ynnor@mm.st>
      Thank you rovf. Yes, I can write the variable into a file, but this sounds complex. I am looking for a simpler solution like your suggestion to right into stdout. Could you elaborate on your answer? Why would I eval it on the output of the perl if I need to access it in the shell. I thought maybe to write to a stdout in the perl, and then somehow get it in the shell. A code snippet would be helpful. Thanks much.

        #!/bin/sh eval `perl -we "print FOO=BAR"` echo $FOO

        -- 
        Ronald Fischer <ynnor@mm.st>
Re: pass perl variable to shell script
by morgon (Priest) on Aug 11, 2010 at 15:17 UTC
    Use command substitution in the shell, e.g.

    #!/bin/sh output=$(perl -e 'print "hello world"'); echo $output;

    If you have a more complex Perl-script then I would put it in it's own file and call it via $(perl script.pl) rathern then embedding it directly in the shell-script as a lot of metacharacters that Perl uses are also special to the shell and escaping all of them properly is a mess.

      Thanks, morgon. But the command substitution will not work for me here. The code snippet I have is just an example to get my point across on how I can access a variable (str3 in this case) in shell after I set it in Perl.
        The command substuition captures the output of the perl-script at the shell-side.

        So if you only have to pass one value you simply print it to standard output in Perl.

        #in perl-script "script.pl" print $variable; #in the shell-script: variable=$(perl script.pl) echo $variable
        If you must pass more than one variable you e.g. print them in a certain format "$var1=$var2=$var3" and parse that on the shell side.