【问题标题】:SED command not generating output file when called from app从应用程序调用时,SED 命令不生成输出文件
【发布时间】:2013-07-02 18:39:10
【问题描述】:

我正在尝试编写一个 Java 程序,它采用 Java 中的字符串并替换 perl 脚本中相应的文本序列。这是我的代码:

    String sedFirstLine = "'s/AAA/"+newFirstLine+"/'";
    String sedNewCntr = "'s/BBB/"+newCntr+"/'";
    String sedNewSpacing = "'s/SPACE/"+newSpacing+"/'";
    String sedNewDmax = "'s/MAX/"+newDmax+"/'";
    String sedInputFile = "/filepath/myPerlScript.pl" 
    String sedOutputFile = "/filepath/myNewPerlScript.pl";
    String[] cmdArray3 = {"sed", "-e", sedFirstLine,"-e", sedNewCntr,"-e", sedNewSpacing,"-e", sedNewDmax, "-e", sedInputFile, ">", sedOutputFile};
    Process runCmd;
    runCmd = Runtime.getRuntime().exec(cmdArray3);

当我运行这个程序时,没有生成输出文件“myNewPerlScript.pl”。我不确定我写的有什么问题。我之前提到的 Java 变量是“newFirstLine”、“newCntr”等。

【问题讨论】:

  • 您的代码实际上从未引用 sedOutputFilesedInputFile。您希望如何使用它们?
  • 您调用 sed 而不是用 Java 中已经存在的正则表达式进行替换的任何特殊原因?
  • 我复制了旧版本的代码。对此很抱歉,但我只是在实际调用 sedOutputFile 和 sedInputFile 的地方对其进行了编辑。
  • 我认为我必须使用“sed”来替换使用 UNIX 的文件中的文本。看起来真的很方便,但我只是无法让它与我的 Java 代码一起工作。
  • 作为一般提示:阅读(并实施)所有When Runtime.exec() won't 的建议。那可能会解决问题。如果没有,它应该提供更多关于失败原因的信息。然后忽略它引用exec 并使用ProcessBuilder 构建Process。还要将 String arg 拆分为 String[] args 以说明本身包含空格的参数。

标签: java bash process sed runtime.exec


【解决方案1】:

这是因为输出重定向(即 > )是 shell 的一项功能。为了重定向命令的输出,您可以通过 shell 调用命令。例如,使用此命令

String[] cmdArray3 = {"bash", "-c", "sed 's/AAA/BBB/' inputfile > output"};
Process runCmd = Runtime.getRuntime().exec(cmdArray3);

应按预期创建输出文件。

【讨论】:

  • 我还需要将每个参数分开吗?还是只有三个参数:shell、“-c”和我的 sed 命令?
  • @JeremyFisher 您将整个命令作为单个String 传递。只应将三个参数传递给exec
【解决方案2】:

ProcessBuilder 版本:

String sedFirstLine = "'s/AAA/"+newFirstLine+"/'";
String sedNewCntr = "'s/BBB/"+newCntr+"/'";
String sedNewSpacing = "'s/SPACE/"+newSpacing+"/'";
String sedNewDmax = "'s/MAX/"+newDmax+"/'";

File directory = new File("/filepath");
File sedInputFile = new File(directory, "myPerlScript.pl"); 
File sedOutputFile = new File(directory, "myNewPerlScript.pl");
List<String> commandLine = new ArrayList<>();
Collections.addAll(commandLine,
    "sed",
    "-e", sedFirstLine,
    "-e", sedNewCntr,
    "-e", sedNewSpacing,
    "-e", sedNewDmax);
ProcessBuilder pb = new ProcessBuilder(commandLine);
pb.directory(directory);
pb.redirectInput(Redirect.from(sedInputFile));
pb.redirectOutput(Redirect.to(sedOutputFile));
Process sed = pb.start();
// Watch sed.getErrorStream() for errors.

ProcessBuilderJavadoc

正如@Chris Stratton 指出的那样,您不必担心 shell,因为 Java 负责重定向。只要确保以某种方式处理错误流即可;如果出现问题并且错误输出过多,则进程可能会阻塞。但是原来的方法也有同样的问题。

【讨论】:

  • "让 JRE 担心 shell。" - 不,不涉及外壳。在这种情况下,Java 正在执行重定向,而不是 shell。
  • 你是对的。我应该写到程序员不必担心shell。这样做的另一个好处是系统可能没有bash 可用,但可能有sed,这有点奇怪,但它可能会发生。我会编辑我的帖子。
  • 是的,不依赖于 shell(或者它可能在自己的命令行上接受命令的能力/语法)使得这个答案非常值得考虑移植性。
  • 如果您真的想要可移植性,您不会求助于外部程序。另一方面,sed 可能比 Java 等价物更快。
【解决方案3】:

只需更改以下行:

String[] cmdArray3 = {"sed", "-e", sedFirstLine,"-e", sedNewCntr,"-e", sedNewSpacing,"-e", sedNewDmax, "-e", sedFile};

到:

String[] cmdArray3 = {"sed", "-e", sedFirstLine,"-e", sedNewCntr,"-e", sedNewSpacing,"-e", sedNewDmax, sedFile};

注意你有额外的 -e 参数。

【讨论】:

  • 额外的 -e 参数实际上是我更改为“>”的旧代码的一部分。对不起。但是我在没有“>”的情况下尝试了它,但仍然没有生成文件:/
  • 用 ">" 试试,它会起作用: String[] cmdArray3 = {"sed", "-e", sedFirstLine,"-e", sedNewCntr,"-e", sedNewSpacing, "-e", sedNewDmax, ">", sedOutputFile };
  • @user1521213 如果像这样构造命令数组,输出重定向字符(即&gt;)将不会被解析,但会作为参数传递给命令。您可以通过 shell 调用命令(如我的回答),或使用ProcessBuilder,如 Eric 的回答。
  • 不,这不起作用。 ">" 是对 shell 的命令,这里没有使用任何 shell。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-13
相关资源
最近更新 更多