Reputation: 93
does anyone know how to use linux grep with the java ProcessBuilder? Why does this code return an empty string when it should 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);
}
}
I also try to echo what I execute with this code:
ProcessBuilder pb = new ProcessBuilder("echo","grep", "\"sing\"", "<<<\"sing\"");
and get the correct result:
grep "sing" <<<"sing"
I finally try to execute the command at the shell and get:
sing
although it is in red font for some reason. So what am I doing wrong?
Upvotes: 1
Views: 2731
Reputation: 121760
what am I doing wrong?
Something which is pretty obvious.
Do you expect, say, execve()
, to understand shell constructs? No.
Well, you shouldn't be expecting ProcessBuilder
to understand those either. Although it is not as low level as execve()
, it is low level enough that the arguments to a command are "raw". Therefore, in your command, <<<"sing"
is passed as is as an argument to grep
; which means grep
views it as a file to read from.
Get that in your head: what you type in the shell is interpreted by the shell; a ProcessBuilder
WILL NOT use a shell to execute its processes, nor will execve()
. Which, in turn, means that you cannot use shell constructs.
If you want to grep
you'll have to feed your process' input with the text you want. But why use grep
when Java has a builtin regex engine is another question, of course.
As to:
although it is in red font for some reason
it is simply text decoration from the grep
command (well, GNU grep at least); see its manpage and the --color
option. In short, in your case, it has detected that your tty had the capabilities to change the color of text and it uses that to decorate the matched text.
Try and:
echo foobar | grep foo
It will echo foobar
with foo
in red.
Upvotes: 3
Reputation: 785376
You can actually run the same command using ProcessBuilder
but you have to make sure it is execute by bash
. I prefer this utility method:
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;
}
Then call it as:
runCmd("grep -o \"sing\" <<<\"icansing\"");
And it gives me this output:
sing
Upvotes: 1