Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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
like image 725
a90 Avatar asked Dec 24 '12 13:12

a90


1 Answers

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
like image 144
ikegami Avatar answered Sep 19 '22 12:09

ikegami