Home > Blockchain >  How to execute dynamically generated perl script from bash?
How to execute dynamically generated perl script from bash?

Time:11-29

1. Problem:

I have a bash script (a 2 liner so far) that calls a perl script that generates a second bash script. I want the first bash script to run the perl script and execute the second (generated) bash script.

2. Background:

This dynamically generated bash script executes fine for both ubuntu bash (via wsl) and cygwin bash on windows (as long as there is only a single bash command):

$(perl -e 'print "ls -ltr"')

3. What I have tried that does not work (Part 1):

The following attempts do not work because bash does not interpret the semicolon or my line feed as a new line and complains (for example) that pwd is not an option for ls.

$(perl -e 'print "ls -ltr;pwd") 
$(perl -e 'print "ls -ltr
pwd") 
$(perl -e 'print "ls -ltr \n pwd")

Is there a way to make these above examples work? I like it because the code is truly a one liner and I'm not creating a new shell for each command.

4. What I have tried that does not work (Part 2):

perl -e 'print `ls -ltr`; print  `pwd`'

Well actually this does work but I don't like this approach because it is slow and it precludes using a bash for-loop in the generated code. It also precludes creating and modify environment variables at the beginning of the bash script and using them later.

5. Having perl write bash script to a file might work?

So what about having my perl dynamically write the bash script to a (uniquely and dynamically named) file and have this perl script print the name of the file to stdout so that the first (calling) bash could store the temporary file name, use "chmod x" and call (execute) it and later delete it.

Is there not a simpler way? It seems like we should be able to make the examples in part 1 work somehow.

Thanks

Siegfried

CodePudding user response:

So, it's almost never a good idea to dynamically-generate Bash code; it's way too easy to write code-generation logic that works for common cases but then misbehaves really badly on cases you haven't thought of. (This is especially true because filenames can contain bizarre characters — spaces, asterisks, backslashes, newlines, quotation marks, initial hyphens, you name it — but even if you're not using filenames in your code-generation logic, there are so many ways this can go wrong.)

But if you're going to do this, then the way you execute the code — the way you tell Bash to read the string containing the code and pass it through the full chain of parsers that interpret ; and newlines and so on — is using eval:

eval "$(perl -e 'print "ls -ltr; pwd"')"

# the above is equivalent to
#    eval 'ls -ltr; pwd'
# which in turn is equivalent to
#    ls -ltr; pwd

Alternatively, you can use bash -c to invoke a separate copy of Bash to run this command:

bash -c "$(perl -e 'print "ls -ltr; pwd"')"

# the above is equivalent to
#    bash -c 'ls -ltr; pwd'
# which is roughly equivalent to
#    ls -ltr; pwd
# except that it runs in a separate shell
  • Related