Perl script runs in terminal but doesn't run when invoked from Java program
Asked Answered
B

1

6

I was running a Perl script that replaces a string with another:

perl -pi.back -e 's/str1/str2/g;' path/to/file1.txt

When I run this command from terminal it well replaces all the occurrences of str1 in the given file to str2. When I run this from java it does access the file but no replacement occurs:

Runtime.getRuntime().exec("perl -pi.back -e 's/str1/str2/g;' path/to/file1.txt");
  • I'm sure it accesses the file (the file seems to be edited in gedit(reload required)).
  • I tried Java ProcessBuilder class but the same result happens.
  • When I use Runtime.exec() or ProcessBuilder with other commands (like gedit newFile.txt) they work well.
  • Ironically, I printed the above perl command from java and take the paste in terminal and the replace operation is done!
  • No exceptions or errors by using those commands. (I used try and catch to ensure this).
  • I also used /usr/bin/perl instead of perl in the cmd to ensure the perl cmd is executed.

So what do you think the problem is?

EDIT:

I solved this problem by just removing the quotes from the command in java. Thanks to @ikegami for help. So the working version is:

perl -pi.back -e s/str1/str2/g; path/to/file1.txt

instead of

perl -pi.back -e 's/str1/str2/g;' path/to/file1.txt
Benitobenjamen answered 24/12, 2012 at 13:38 Comment(7)
exec() returns you a Process, it has getInputStream() and getErrorStream() methods which return you whatever output the process creates. See what this process outputs.Transformer
Depending on the OS, your Java program probably does not have the path to Perl. You'll need to put the full path in to the Perl binary. That's not the only way to do it, but one of the simplest ways.Malaguena
@DenisTulskiy I already did this. They output nothing.Benitobenjamen
@Malaguena I did this but also same problem.Benitobenjamen
@ikegami I owe you one. Removing the quotes get it working! Thanks but I wanna ask why should I remove the quotes?Benitobenjamen
What's the difference between the shell commands echo "foo's" and echo foo\'s? None whatsoever. Both pass foo's to echo.Conceivable
What I am suggesting is that you print your PATH in both instances. From the command line, it's simple. From the program, you'll need to get env from a Java --> sys-exec routine and print the PATH that way.Malaguena
C
5

exec uses StringTokenizer to parse the command, which apparently just splits on whitespace.

Take for example the following shell command (similar but different than yours):

perl -pi.back -e 's/a/b/g; s/c/d/g;' path/to/file1.txt

For it, StringTokenizer produces the following command and arguments:

  • perl (command)
  • -pi.back
  • -e
  • 's/a/b/g;
  • s/c/d/g;'
  • path/to/file1.txt

That's completely wrong. The command and arguments should be

  • perl (command)
  • -pi.back
  • -e
  • s/a/b/g; s/c/d/g; (Note the lack of quotes.)
  • path/to/file1.txt

You could pass those above to exec(String[] cmdarray). Or if you don't have the option of parsing the command, you could actually invoke a shell to parse it for you by passing the following to exec(String[] cmdarray):

  • sh (command)
  • -c
  • perl -pi.back -e 's/a/b/g; s/c/d/g;' path/to/file1.txt
Conceivable answered 24/12, 2012 at 14:27 Comment(1)
You should try perl -le'print for @ARGV' perl -pi.back -e 's/str1/str2/g;' path/to/file1.txt and see what is actually passed to Perl by the shell. You should also try it without the (unnecessary) space after the -e.Conceivable

© 2022 - 2024 — McMap. All rights reserved.