0

I am trying to use awk from java. I wrote below code but there is no output.

public class ShellScriptExecution {

    public static void main (String[] a) {
        ShellScriptExecution shellsc = new ShellScriptExecution();
        String command = "awk '/Ayushi/ {print}' /home/ayushi/Desktop/testAwk.txt ";
        String op = shellsc.execute(command, a);
        System.out.println(op);
    }

    private String execute(String command, String[] a) {
        StringBuffer sb = new StringBuffer();
        Process p;
        try {

            //
            //

            p = Runtime.getRuntime().exec(command);
            p.waitFor();
            BufferedReader reader = 
                    new BufferedReader(new InputStreamReader(p.getInputStream()));

                String line = "";           
            while ((line = reader.readLine())!= null) {
                sb.append(line + "\n");
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }
}

Please provide some help on how to use awk in java? And if any other way to do it ?

samabcde
  • 6,988
  • 2
  • 25
  • 41
AyushiRaj
  • 1
  • 2
  • Make sure you read error stream from the process executing the command as it could returning an error. Does your environment where you execute this have `awk` available on the command line btw? – diginoise Sep 10 '18 at 09:37

3 Answers3

2

The other answers aren't invalid, but there are multiple issues with your code. Yes, you're not managing your reads of error/output correctly. But in addition, you're making the mistake of thinking that Runtime.getRuntime().exec is bash-like. It isn't.

When you type this:

awk '/Ayushi/ {print}' /home/ayushi/Desktop/testAwk.txt

in bash, bash preprocesses a lot of that before it actually invokes awk. It does these things:

  1. It uses the environment PATH variable to figure out that awk is a reference to presumably /usr/bin/awk.
  2. It parses the string /Ayushi {print} including that space as the first parameter. As part of this, the single quotes are consumed by bash.
  3. It takes the path to testAwk and sees nothing to do (it isn't quoted and contains no variables or stars or question marks).
  4. That trailing space, however... that is eliminated.

Therefore, it will invoke /usr/bin/awk with as parameters ["/Ayushi {print}", "/home/ayushi/Desktop/testAwk.txt"]

Java is not bash. It is going to do either none of those things, or only a few of those things, depending on the OS you run java on. It is best to assume java will do none of those things. (Also, assume something like *.txt just is not going to work. In windows it may or may not work, in linux and mac that definitely would not work. Expanding *.txt to a list of files that match that wildcard is something bash does).

For starters, never use Runtime.getRuntime().exec(). Always use ProcessBuilder, or at the very least, the exec method which takes a list of parameters instead of a single string. Then, pass the following as command line argument:

ProcessBuilder pb = new ProcessBuilder(
  "/usr/bin/awk",
  "/Ayushi {print}",
  "/home/ayushi/Desktop/testAwk.txt"
);
// configure other things, such as redirecting error to output and such...
Process p = pb.start();
// start handling the outputs.

Then take it from there. You can peruse the docs on ProcessBuilder for useful things to set prior to actually invoking, and things you can do with your Process p variable.

NB: It looks like you're running things inside some linux emulation layer inside windows, that's definitely going to make things more complicated.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
0

Just a suggestion because I still can't comment due to insufficient reputations points. Why don't you just create a native shell script and do your awk commands there and use java to trigger the said shell script? I think that's more convenient. In this question you would like to use awk in java but in reality it's a "command line utility" that can be used in shell scripts. If you really want to use awk in java then maybe try searching for a third party library.

Oneb
  • 145
  • 1
  • 12
0

You need to get output of your process. So you can modify the command, so it prints result into a text file. After the process finishes its job, you can read the file.

  runcomand > output_file.txt

Or you can create a stream and read the output example is here.

BufferedReader stdInput = new BufferedReader(new 
InputStreamReader(proc.getInputStream()));

BufferedReader stdError = new BufferedReader(new 
InputStreamReader(proc.getErrorStream()));

I did a similar thing with CURL. I needed to run a CURL process from a Java program and get output.

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import static com.my.util.FileUtils.saveContent;

public class CurlProcess {

    private static final String CURL = "curl";
    private static final String RESPONSE_DIRECTORY = "C:/responses";

    static {
        FileUtils.createDirectory(RESPONSE_DIRECTORY);
    }

    public void execute(String url, String filename) {
        ProcessBuilder pb = new ProcessBuilder(
                CURL,
                "-s",
                "-i",
                url);

        pb.directory(new File(RESPONSE_DIRECTORY));
        pb.redirectErrorStream(true);
        Process p = null;

        String outputFile = RESPONSE_DIRECTORY + "/" + filename;
        try {
            p = pb.start();
            InputStream is = p.getInputStream();
            OutputStream os = new FileOutputStream(outputFile);
            saveContent(is, os);

            is.close();
        } catch (IOException e) {
            throw new RuntimeException("Failed to start curl process.", e);
        }
    }
}
Yan Khonski
  • 12,225
  • 15
  • 76
  • 114