一个人不只是简单地进入 ProcessBuilder

One does not simply grep into ProcessBuilder

有谁知道如何将 linux grep 与 java ProcessBuilder 一起使用?为什么这段代码 return 应该是空字符串 return "sing" ?

import java.io.*;
import java.util.*;

public class Test2 {

public static void main(String[] args) throws InterruptedException,IOException{
    String line;

    // Initiate grep process.
    ProcessBuilder pb = new ProcessBuilder("grep", "\"sing\"", "<<<\"sing\"");
    Process p = pb.start();
    p.waitFor();

    // Get grep output:     
    BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));

    StringBuilder builder = new StringBuilder();
    line = null;
    while ( (line = reader.readLine()) != null) {
        builder.append(line);
        builder.append(System.getProperty("line.separator"));
    }
    String result = builder.toString();
    System.out.println(result);     
}
}

我也试着回显我用这段代码执行的内容:

ProcessBuilder pb = new ProcessBuilder("echo","grep", "\"sing\"", "<<<\"sing\"");

并得到正确的结果:

 grep "sing" <<<"sing"

我终于尝试在 shell 处执行命令并得到:

sing

尽管出于某种原因它是红色字体。那我做错了什么?

what am I doing wrong?

很明显的东西。

您希望 execve() 理解 shell 结构吗?号

嗯,您也不应期望 ProcessBuilder 理解这些内容。虽然它不像execve()那么低级,但它足够低级到命令的参数是"raw"。因此,在您的命令中,<<<"sing" 作为参数传递给 grep;这意味着 grep 将其视为要读取的文件。

记住这一点:您在 shell 中键入的内容由 shell 解释; a ProcessBuilder 不会 使用 shell 来执行其进程,execve() 也不会。反过来,这意味着您 不能 使用 shell 结构。

如果您想要 grep,则必须 feed your process' input 使用您想要的文字。但是,为什么在 Java 具有内置正则表达式引擎时使用 grep 是另一个问题,当然。

至于:

although it is in red font for some reason

它只是来自 grep 命令的文本装饰(好吧,至少是 GNU grep);请参阅其联机帮助页和 --color 选项。简而言之,在您的情况下,它检测到您的 tty 具有更改文本颜色的功能,并使用它来装饰匹配的文本。

尝试并:

echo foobar | grep foo

它会以红色回显 foobarfoo

您实际上可以 运行 使用 ProcessBuilder 相同的命令,但您必须确保它是由 bash 执行的。我更喜欢这个实用方法:

public static int runCmd(final String command) {
    Process process=null;
    int ret = 0;
    String[] finalCommand = new String[] { "bash", "-c", command };

    try {
        final ProcessBuilder processBuilder = new ProcessBuilder(finalCommand);
        processBuilder.redirectErrorStream(true);
        process = processBuilder.start();
        ret = process.waitFor();
        // stdout+stderr
        InputStreamReader isr = new InputStreamReader( process.getInputStream() );
        BufferedReader br = new BufferedReader(isr);
        String line;
        while ((line = br.readLine()) != null) {
          System.out.println(line);
        }
        //System.out.println("Program terminated!");
        process.destroy();
        br.close();
        isr.close();
    } 
    catch (IOException|InterruptedException e) { 
        e.printStackTrace(); 
    } 
    return ret;
}

然后将其命名为:

runCmd("grep -o \"sing\" <<<\"icansing\"");

它给了我这个输出:

sing