Мне нужно соединить два огромных файла на основе нескольких столбцов. Символ вертикальной черты (|) является разделителем в обоих файлах.
Прямо сейчас я генерирую команду соединения unix, записываю ее в сценарий оболочки, а затем выполняю сценарий оболочки с помощью ProcessBuilder для получения желаемого результата.
Команда выглядит примерно так:
join -a 1 -a 2 -t \| -1 1 -2 1 -o 1.3,1.4,1.5,1.6,1.7,2.3,2.4,2.5,2.6,2.7 <(<"/home/input file 1" awk -F'|' 'NR>1{print $3"~&~"$4"|"$0}' | sort -k1 -t\| ) <(<"/home/input file 2" awk -F'|' 'NR>1{print $3~&~$4"|"$0}' | sort -k1 -t\| ) > "/home/output file"
Это работает, как ожидалось.
Я пытаюсь пропустить этап записи команды в сценарий оболочки с помощью bash -c. Но я сталкиваюсь с проблемами в основном из-за двойных кавычек (") и доллара ($) в команде awk. Я пытался избежать их, используя обратную косую черту, но это было бесполезно.
код Java, который я использую в настоящее время,
long pid = -1;
try {
StringBuilder completeCommand = new StringBuilder();
for(String s: commands){
completeCommand.append(s);
completeCommand.append(" ");
}
completeCommand.append(" > \"");
completeCommand.append(outputDir + File.separator + outputFileName);
completeCommand.append("\"");
File fileOutputDir = new File(outputDir);
fileOutputDir.mkdirs();
Files.writeString(Path.of(outputDir + File.separator + scriptName),
completeCommand.toString(),
new OpenOption[]{StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE,
StandardOpenOption.CREATE});
ProcessBuilder processBuilder = new ProcessBuilder("bash", "\"" + outputDir + File.separator + scriptName + "\"");
Process p = processBuilder.start();
pid = p.pid();
p.waitFor();
return pid;
} catch (IOException | InterruptedException e) {
log.error("Error in running join command" , e);
return pid;
}
Когда я попытался использовать bash -c, я просто изменил оператор ProcessBuilder, как показано ниже:
ProcessBuilder processBuilder = new ProcessBuilder("bash", "-c", completeCommand.toString());
Это не вызывает ошибок, но создает пустой файл.
Как я могу решить эту проблему?
Любая помощь или предложения были бы замечательными.
Спасибо
Опубликованный вами код - нет a минимальный воспроизводимый пример. Что такое переменная commands
в петле for
? Помните, что обычно вам нужно разбить команду на отдельные слова и создать List
или массив из этих слов и передать этот List
(или массив) конструктору ProcessBuilder
. Думали ли вы о написании сценария оболочки и запуске этого сценария с ProcessBuilder
?
@Abra, Прямо сейчас пишу команду в скрипт и выполняю скрипт. Я пытаюсь пропустить этот шаг. Является ли это возможным ? Я постараюсь перепостить код, чтобы он был минимальным и воспроизводимым.
Трудно ответить, не увидев commands
, скорее всего, это связано с побегом. Вы игнорируете сообщения об ошибках при запуске processBuilder.redirectOutput(stdout);
и processBuilder.redirectErrorStream(true);
.
@DuncG, я отредактировал вопрос, указав соответствующие детали, как и требовалось. Спасибо