0

I was trying to run a unix command in java to overlook the double quotation mark in a parsed file:

    for(int i = 0; i < numTables; i++){
        try{
            String command = "sed -e \'s/\"/\"\"/g\' -e \'s/^/\"/\' -e \'s/$/\"/\' -e \'s/<>/\"<>\"/g\' input.dat > output.dat";
            Process p = Runtime.getRuntime().exec(command);
        } catch(IOException ioe){
            System.out.println("Error executing command");
        }
    }

However, typing the identical command on the terminal directly would work. Any idea what went wrong? Thank you!

Update: In fact, I tried the following (using array instead of just a String), it failed too:

            String[] command = new String[] {"sed", "-e", "\'s/\"/\"\"/g\'", "-e", "\'s/^/\"/\'", "-e", "\'s/$/\"/\'", "-e", "\'s/<>/\"<>\"/g\'", prefixedFileList.get(i), ">", fileList.get(i)};
            Process p = Runtime.getRuntime().exec(command);

Any thoughts?

As a clearer picture, the corresponding plain text that would be executed on unix terminal would be

sed -e 's/"/""/g' -e 's/^/"/' -e 's/$/"/' -e 's/<>/"<>"/g' input.dat > output.dat
Clueless Gorilla
  • 1,199
  • 2
  • 10
  • 16

3 Answers3

0

Well in some special character you are not putting \ ? Can you put the same.

Hussain Shabbir
  • 14,801
  • 5
  • 40
  • 56
0

It helps to distinguish exactly what a program argument is. When you execute this line:

sed -e 's/"/""/g' -e 's/^/"/' -e 's/$/"/' -e 's/<>/"<>"/g' input.dat > output.dat

The main method of the sed binary receives these strings in its argv:

  • sed
  • -e
  • s/"/""/g
  • -e
  • s/^/"/
  • -e
  • s/$/"/
  • -e
  • s/<>/"<>"/g
  • input.dat

Notice that the single-quotes (') are not part of the program arguments. The single-quotes are interpreted by the shell (bash, csh, etc.). They tell the shell not to evaluate or parse what's inside them. The shell takes a single-quoted string and passes it to the program as is, but the single-quotes are not part of the argument. They are for the benefit of the shell only.

Also notice that the file redirection, > output.dat, is not part of the program arguments. File redirection is parsed by the shell. It is not a program's job to know whether its standard output is being redirected; the program writes to standard output regardless, and the operating system performs the redirection. If you try to pass > output.dat as program arguments, sed will look for an additional input file named > and an additional input file named output.dat.

It is always better to call a Runtime.exec method which takes an array rather than a single String, as you seem to already know. Even better than that is to use the ProcessBuilder class, which can do output redirection, essentially duplicating the functionality of > in the shell:

ProcessBuilder builder = new ProcessBuilder(
    "sed",
    "-e",
    "s/\"/\"\"/g",
    "-e",
    "s/^/\"/",
    "-e",
    "s/$/\"/",
    "-e",
    "s/<>/\"<>\"/g",
    "input.dat");
builder.redirectOutput(new File("output.dat"));
builder.redirectError(ProcessBuilder.Redirect.INHERIT);

Process p = builder.start();
VGR
  • 40,506
  • 4
  • 48
  • 63
  • This seems to be a pretty legitimate answer. However, when I tried, it still fails........... :( – Clueless Gorilla Oct 20 '13 at 16:15
  • How does it fail? Are you seeing an exception? – VGR Oct 20 '13 at 19:35
  • Try adding `builder.redirectError(ProcessBuilder.Redirect.INHERIT);` so any errors displayed by **sed** are visible in your program's output. I've updated my answer accordingly. – VGR Oct 20 '13 at 20:48
0

One of the best solutions it to use Apache Commons Exec library.

Below is my favourite usage :

CommandLine cmdLine = new CommandLine("AcroRd32.exe");
cmdLine.addArgument("/p");
cmdLine.addArgument("/h");
DefaultExecutor executor = new DefaultExecutor();
executor.setExitValue(1);
int exitValue = executor.execute(cmdLine);

We don't have to worry about encapsulating arguments properly using this form.

coding_idiot
  • 13,526
  • 10
  • 65
  • 116