Нет ответа при запуске сценария оболочки AWK с использованием java

Я пытаюсь использовать awk из java. Я написал код ниже, но вывода нет.

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

Пожалуйста, предоставьте некоторую помощь о том, как использовать awk в java? А есть ли другой способ сделать это?

Убедитесь, что вы читаете поток ошибок из процесса, выполняющего команду, поскольку он может вернуть ошибку. Есть ли в вашей среде, где вы выполняете это, awk, доступный в командной строке, кстати?

diginoise 10.09.2018 11:37
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
545
3

Ответы 3

Просто предложение, потому что я все еще не могу комментировать из-за недостаточной репутации. Почему бы вам просто не создать собственный сценарий оболочки, выполнить там свои команды awk и использовать java для запуска указанного сценария оболочки? Думаю, так удобнее. В этом вопросе вы хотели бы использовать awk в java, но на самом деле это «утилита командной строки», которую можно использовать в сценариях оболочки. Если вы действительно хотите использовать awk в java, возможно, попробуйте поискать стороннюю библиотеку.

Просто придирка, но awk не является "командой bash". Вероятно, вы имеете в виду "утилиту командной строки"

Federico klez Culloca 10.09.2018 11:34

Вам нужно получить результат вашего процесса. Итак, вы можете изменить команду, так что выводит результат в текстовый файл. После того, как процесс завершит свою работу, вы можете прочитать файл.

  runcomand > output_file.txt

Или вы можете создать поток и прочитать вывод пример здесь.

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

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

Я сделал то же самое с CURL. Мне нужно было запустить процесс CURL из программы Java и получить результат.

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

Другие ответы недействительны, но с вашим кодом есть несколько проблем. Да, вы неправильно управляете чтением ошибок / выводов. Но, кроме того, вы ошибаетесь, полагая, что Runtime.getRuntime (). Exec похож на bash. Это не так.

Когда вы набираете это:

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

в bash, bash многое из этого предварительно обрабатывает, прежде чем фактически вызовет awk. Он делает следующее:

  1. Он использует переменную среды PATH, чтобы выяснить, что awk является ссылкой на предположительно /usr/bin/awk.
  2. Он анализирует строку /Ayushi {print}, включая этот пробел в качестве первого параметра. В рамках этого bash использует одинарные кавычки.
  3. Он выбирает путь к testAwk и не видит ничего, что нужно делать (он не цитируется и не содержит переменных, звездочек или вопросительных знаков).
  4. Однако это конечное пространство ... оно устранено.

Следовательно, он вызовет / usr / bin / awk с параметрами ["/ Ayushi {print}", "/home/ayushi/Desktop/testAwk.txt"]

Java - это не bash. Он не будет делать ничего из этого или только некоторые из этих вещей, в зависимости от ОС, в которой вы запускаете java. Лучше предположить, что Java не будет делать ничего из этого. (Также предположим, что что-то вроде *.txt просто не будет работать. В Windows это может работать, а может и не работать, в Linux и Mac это определенно не будет работать. Расширение *.txt до списка файлов, соответствующих этому шаблону, - это то, что делает bash).

Для начала никогда не используйте Runtime.getRuntime (). Exec (). Всегда используйте ProcessBuilder или, по крайней мере, метод exec, который принимает список параметров вместо одной строки. Затем передайте в качестве аргумента командной строки следующее:

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.

NB: Похоже, вы запускаете что-то внутри некоторого слоя эмуляции Linux внутри окон, что определенно усложнит задачу.

Другие вопросы по теме