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
wkl
  • 77,184
  • 16
  • 165
  • 176
a90
  • 63
  • 5
  • `exec()` returns you a `Process`, it has `getInputStream()` and `getErrorStream()` methods which return you whatever output the process creates. See what this process outputs. – Denis Tulskiy Dec 24 '12 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. – octopusgrabbus Dec 24 '12 at 14:02
  • @DenisTulskiy I already did this. They output nothing. – a90 Dec 24 '12 at 14:02
  • @octopusgrabbus I did this but also same problem. – a90 Dec 24 '12 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? – a90 Dec 24 '12 at 14:16
  • What's the difference between the shell commands `echo "foo's"` and `echo foo\'s`? None whatsoever. Both pass `foo's` to `echo`. – ikegami Dec 24 '12 at 14:19
  • 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. – octopusgrabbus Dec 24 '12 at 16:07

1 Answers1

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
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • 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`. – ikegami Dec 24 '12 at 14:33