使用Java运行AWK Shell脚本时无响应

问题描述:

我正在尝试从Java使用awk.我写了下面的代码,但没有输出.

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();
    }
}

请提供有关如何在Java中使用awk的帮助?还有其他方法吗?

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

其他答案不是无效的,但是您的代码存在多个问题.是的,您无法正确管理错误/输出的读取.但是除此之外,您还误以为Runtime.getRuntime().exec类似于bash.不是.

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.

当您键入以下内容时:

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

在bash中,bash在实际调用awk之前对其进行了很多预处理.它执行以下操作:

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

  1. 它使用环境PATH变量来确定awk是对/usr/bin/awk的引用.
  2. 它将解析包含该空格作为第一个参数的字符串/Ayushi {print}.在这种情况下,bash会使用单引号.
  3. 它采用了testAwk的路径,却无所事事(它没有被引用并且不包含变量,星号或问号).
  4. 但是,尾随的空间...被消除了.
  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.

因此,它将使用参数["/Ayushi {print}","/home/ayushi/Desktop/testAwk.txt"]调用/usr/bin/awk

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

Java不是bash .根据运行Java的操作系统,它要么不执行任何操作,要么不执行任何操作.最好假设Java不会做任何事情. (此外,假设像*.txt这样的东西将无法工作.在Windows中,它可能会或可能不会工作,在linux和mac上肯定不会工作.将*.txt扩展到与该通配符匹配的文件列表是很重要的事情. bash可以).

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).

对于初学者,请勿使用Runtime.getRuntime().exec().始终使用ProcessBuilder,或者至少使用exec方法,该方法采用参数列表而不是单个字符串.然后,将以下内容作为命令行参数传递:

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.

然后从那里拿走.您可以仔细阅读ProcessBuilder上的文档,以了解在实际调用之前要进行的有用设置以及可以使用Process p变量进行的操作.

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:看来您正在Windows内的某些Linux仿真层中运行事物,这肯定会使事情变得更复杂.

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