0

我试图在java中运行一个unix命令来忽略解析文件中的双引号:

    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");
        }
    }

但是,直接在终端上输入相同的命令就可以了。知道出了什么问题吗?谢谢!

更新:事实上,我尝试了以下方法(使用数组而不是字符串),它也失败了:

            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);

有什么想法吗?

作为更清晰的图片,将在 unix 终端上执行的相应纯文本将是

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

3 回答 3

0

它有助于准确区分程序参数是什么。当您执行此行时:

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

sed二进制文件的main方法在其 argv 中接收这些字符串:

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

请注意,单引号 ( ') 不是程序参数的一部分。单引号由 shell(bash、csh 等)解释。他们告诉外壳不要评估或解析其中的内容。shell 接受一个单引号字符串并将其按原样传递给程序,但单引号不是参数的一部分。它们只是为了 shell 的利益。

另请注意,文件重定向> output.dat不是程序参数的一部分。文件重定向由 shell 解析。知道它的标准输出是否被重定向不是程序的工作。无论如何,程序都会写入标准输出,并且操作系统会执行重定向。如果您尝试> output.dat作为程序参数传递,sed将查找名为>的附加输入文件和名为output.dat.

正如您似乎已经知道的那样,调用采用数组而不是单个字符串的 Runtime.exec 方法总是更好。比这更好的是使用ProcessBuilder可以进行输出重定向的类,基本上复制>了 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();
于 2013-10-20T13:54:33.347 回答
0

好吧,在某些特殊字符中,您没有放 \ ?能不能放一样。

于 2013-10-20T10:49:32.223 回答
0

使用Apache Commons Exec库的最佳解决方案之一。

以下是我最喜欢的用法:

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

我们不必担心使用这种形式正确封装参数。

于 2013-10-20T21:13:37.120 回答