【问题标题】:Perl script runs in terminal but doesn't run when invoked from Java programPerl 脚本在终端中运行,但在从 Java 程序调用时不运行
【发布时间】:2012-12-24 13:38:51
【问题描述】:

我正在运行一个用另一个字符串替换字符串的 Perl 脚本:

perl -pi.back -e 's/str1/str2/g;' path/to/file1.txt

当我从终端运行此命令时,它会将给定文件中所有出现的str1 替换为str2。当我从 java 运行它时,它确实访问了该文件,但没有发生替换:

Runtime.getRuntime().exec("perl -pi.back -e 's/str1/str2/g;' path/to/file1.txt");
  • 我确定它访问了该文件(该文件似乎在 gedit 中进行了编辑(需要重新加载))。
  • 我尝试了 Java ProcessBuilder 类,但结果相同。
  • 当我将Runtime.exec()ProcessBuilder 与其他命令(如gedit newFile.txt)一起使用时,它们运行良好。
  • 具有讽刺意味的是,我从 java 打印了上面的 perl 命令并在终端中粘贴并完成替换操作!
  • 使用这些命令不会出现异常或错误。 (我使用 try 和 catch 来确保这一点)。
  • 我还在cmd中使用/usr/bin/perl而不是perl来确保perl cmd被执行。

那么你认为问题出在哪里?

编辑:

我通过从 java 中的命令中删除引号解决了这个问题。感谢@ikegami 的帮助。 所以工作版本是:

perl -pi.back -e s/str1/str2/g; path/to/file1.txt

而不是

perl -pi.back -e 's/str1/str2/g;' path/to/file1.txt

【问题讨论】:

  • exec() 会返回一个Process,它有getInputStream()getErrorStream() 方法可以返回进程创建的任何输出。看看这个过程输出了什么。
  • 根据操作系统,您的 Java 程序可能没有 Perl 的路径。您需要将完整路径放入 Perl 二进制文件中。这不是唯一的方法,而是最简单的方法之一。
  • @DenisTulskiy 我已经这样做了。他们什么也没输出。
  • @octopusgrabbus 我这样做了,但也有同样的问题。
  • @ikegami 我欠你一个。删除引号让它工作!谢谢,但我想问我为什么要删除引号?

标签: java perl runtime.exec


【解决方案1】:

exec 使用StringTokenizer 来解析命令,这显然只是在空格处拆分。

以以下 shell 命令为例(与您的类似但不同):

perl -pi.back -e 's/a/b/g; s/c/d/g;' path/to/file1.txt

为此,StringTokenizer 产生以下命令和参数:

  • perl(命令)
  • -pi.back
  • -e
  • 's/a/b/g;
  • s/c/d/g;'
  • path/to/file1.txt

这是完全错误的。命令和参数应该是

  • perl(命令)
  • -pi.back
  • -e
  • s/a/b/g; s/c/d/g;(注意没有引号。)
  • path/to/file1.txt

您可以将上述内容传递给exec(String[] cmdarray)。或者,如果您没有解析命令的选项,您实际上可以调用一个 shell 来为您解析它,方法是将以下内容传递给 exec(String[] cmdarray)

  • sh(命令)
  • -c
  • perl -pi.back -e 's/a/b/g; s/c/d/g;' path/to/file1.txt

【讨论】:

  • 您应该尝试perl -le'print for @ARGV' perl -pi.back -e 's/str1/str2/g;' path/to/file1.txt 并查看shell 实际传递给Perl 的内容。您还应该尝试在-e 后面不带(不必要的)空格。
猜你喜欢
  • 1970-01-01
  • 2011-08-15
  • 2013-06-20
  • 1970-01-01
  • 2012-03-25
  • 2012-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多