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
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. Commented Dec 24, 2012 at 13:53
  • 1
    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. Commented Dec 24, 2012 at 14:02
  • @DenisTulskiy I already did this. They output nothing. Commented Dec 24, 2012 at 14:02
  • @octopusgrabbus I did this but also same problem. Commented Dec 24, 2012 at 14:04
  • @ikegami I owe you one. Removing the quotes get it working! Thanks but I wanna ask why should I remove the quotes? Commented Dec 24, 2012 at 14:16

1 Answer 1

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
Sign up to request clarification or add additional context in comments.

1 Comment

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.