【问题标题】:Executing grep command on Linux from Java always returning null从 Java 在 Linux 上执行 grep 命令总是返回 null
【发布时间】:2017-01-21 05:27:07
【问题描述】:

我正在从 java 对 linux 文件执行 grep 命令。对于以下代码,它总是返回 null。

Process p;
String matchStr="testmatch";
String output = null;
try {
    String command = "grep \""+matchStr+"\" "+ filename;
    System.out.println("Running command: " + command);

    p = Runtime.getRuntime().exec(command);

    System.out.println("***********************************");
    System.out.println("***********************************");
    System.out.println("***********************************");

    p.waitFor();
    BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));

    while (br.readLine() != null) {
        System.out.println("in while loop");
        System.out.println("in while loop");
        System.out.println("in while loop");
        System.out.println(output);
        System.out.println("***********************************");
        System.out.println("***********************************");
        System.out.println("***********************************");
        System.out.println("***********************************");

        // Process your output here
    }

    System.out.println("exit: " + p.exitValue());
    p.destroy();
} catch (Exception e) {
    e.printStackTrace();
}

如果我直接 grep 它会显示输出,但从 java 它永远不会进入 while 循环。 请在这里提出问题。

【问题讨论】:

  • 您是否提供了要搜索的文件的完整路径? filename 有完整的变量路径吗?
  • @Inian 是的,它是文件的完整路径。它在读取文件时也没有抛出错误。
  • 你能根据你的喜好运行 grep 调用显式 shell shbash,例如 String[] command = {"/bin/sh", "-c", "grep \""+matchStr+"\" " 吗?
  • 好的,让我试试@Inian
  • @Inian 你能给我举例说明如何在这个命令中添加文件名吗?

标签: java linux bash


【解决方案1】:

问题是你没有向output 写任何东西,所以它仍然是null。我猜你必须像这样重写你的while循环

while ((output = br.readLine()) != null) {
    // Process your output here
}

请注意,由于它的模糊性,大多数样式检查不鼓励这种语法

在 while 循环之后放置 p.waitFor() 也是一个好主意,这样 grep 就不会挂在 flushig std(err|out) 上。

更新

此外,使用ProcessBuilder(自 起可用)而不是Runtime.getRuntime().exec(...) 也是一个好主意,因为您将对流程有更多控制权,即

final ProcessBuilder builder = new ProcessBuilder();
builder.command("grep", matchStr, filename);

// redirect stderr to stdout
builder.redirectErrorStream(true);

final Process process = builder.start();

BufferedReader br = new BufferedReader(
    new InputStreamReader(process.getInputStream()));
String output = null;
while ((output = br.readLine()) != null) {
    System.out.println(output);

    // Process your output here
}

process.waitFor();

【讨论】:

  • 其实我在用 while ((output = br.readLine()) != null) 这个但是没用
  • @kirti 如果您更改 while 循环,您是否编写程序打印 in while loop
  • @kiri 表示 grep 执行失败。您可以从更新运行代码以查看 stderr 输出并将其写回此处吗?
  • thankyou.. 它通过更改@inian 建议的命令开始工作
  • 这个解决方案比较好,因为:1.它直接健壮地调用grep,没有添加shell评估步骤,2.它在读取它的输出之前不等待进程,避免了长输出的死锁。 3. 它使用 ProcessBuilder,而不是旧的、不确定的、不可扩展的 Runtime.exec。 +1。它在正确使用时确实有效,您只需确保文件名和匹配字符串是您想要的文字字符串,而不是例如在其中任何一个空格前添加反斜杠
【解决方案2】:

将您的代码转换为https://stackoverflow.com/help/mcve 后,它对我有用。

这里文件不存在:

robert@habanero:~$ rm /home/robert/greptest.txt

robert@habanero:~$ javac GrepTest.java && java GrepTest

运行命令:grep test /home/robert/greptest.txt

退出:2

现在文件确实存在但不包含要查找的文本:

robert@habanero:~$ echo not found > /home/robert/greptest.txt

robert@habanero:~$ javac GrepTest.java && java GrepTest

运行命令:grep test /home/robert/greptest.txt

退出:1

现在文件存在并包含文本:

robert@habanero:~$ echo test this > /home/robert/greptest.txt

robert@habanero:~$ javac GrepTest.java && java GrepTest

运行命令:grep test /home/robert/greptest.txt

测试一下

退出:0

代码如下:

import java.io.*;

public class GrepTest {
    public static void main(String[] args) throws Exception {
        String command = "grep test /home/robert/greptest.txt";
        System.out.println("Running command: " + command);
        Process p = Runtime.getRuntime().exec(command);
        p.waitFor();
        BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String output;
        while ((output = br.readLine()) != null) {
            System.out.println(output);
        }
        System.out.println("exit: " + p.exitValue());
        p.destroy();
    }
}

【讨论】:

    【解决方案3】:

    我最近在一个类似的问题上苦苦挣扎,我相信我找到的解决方案也可以解决您的问题(尽管您的问题正如其他人所指出的那样格式不正确)。

    问题与搜索字符串周围的引号有关,

    \""+matchStr+"\"
    

    java exec 命令会直接将这些传递给 grep 命令,而不是搜索 matchStr,grep 将寻找“matchStr”,结果将不是您所期望的。

    这也适用于将命令作为数组执行的情况

    final Process process = Runtime.getRuntime().exec(new String[] { "grep", "-C1000", searchString, fileName } );
    

    传递普通的 searchString 而不在字符串中包含引号。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-23
      • 2012-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-09
      相关资源
      最近更新 更多