Либо получить исходное возвращаемое значение из xargs, либо смоделировать xargs

Я работаю с Bash. У меня есть файл F, содержащий аргументы командной строки для Java-программы, и мне нужно хранить оба вывода Java-программ, т. Е. Вывод на стандартный вывод и выходное значение. Хранение стандартного вывода работает через

cat F | xargs java program > Output

Но xargs не дает доступа к коду выхода программы Java. Итак, я разделил его, запустив программу дважды, один раз для стандартного вывода, один раз для кода выхода - но получить код завершения и запустить его правильно кажется невозможным. Можно попробовать

java program $(cat F)

но это не работает, если F содержит, например, " ", а именно один аргумент командной строки для программы, которая является пробелом. Проблема заключается в расширении аргумента $(cat F).

Теперь я не вижу способа обойти эту проблему? Я не хочу "$(cat F)", так как я хочу, чтобы $ (cat F) расширялся во множество строк - но я не хочу дальнейшего расширения этих строк.

С другой стороны, если бы существовал лучший xargs, предоставляющий доступ к исходному значению выхода, это решило бы проблему, но я не знаю об этом.

3 ответа

Делает ли это то, что вы хотите?

cat F | xargs bash -c 'java program "$@"; echo "Returned: $?"' - > Output

Или, как правильно указывает @rici, избегайте UUOC

xargs bash -c 'java program "$@"; echo "Returned: $?"' - < F > Output

В качестве альтернативы что-то вроде (хотя я не продумал все последствия этого, так что может быть причина, по которой это плохая идея).

{ sed -e 's/^/java program /' F | bash -s; echo "Returned $?"; } > Output

Это позволяет хранить код возврата в переменной xargs версий нет (по крайней мере, за пределами xargsпорожденный панцирь.

sed -e 's/^/java program /' F | bash -s > Output; ret=$?

Использовать ${program} Переменная оболочки просто разверните его напрямую.

xargs bash -c 'java '"${program}"' "$@"; echo "Returned: $?"' - < F > Output

sed -e 's/^/java '"${program}"' /' F | bash -s > Output; ret=$?

Просто остерегайтесь персонажей, которые "волшебны" при замене s/// команда.

Если у вас есть GNU Parallel (и вы не против дополнительного вывода на STDERR):

cat F | parallel -Xj1 --halt 1 java program > Output
echo $?

Боюсь, вопрос на самом деле не очень понятен, поэтому я сделаю предположения здесь явными:

  1. Файл F имеет один аргумент на строку, причем все пробелы, отличные от символов новой строки, являются значимыми, и нет необходимости заменять экранирование обратной косой чертой, например \t,

  2. Вам нужно всего лишь один раз вызвать java-программу со всеми аргументами.

  3. Вам необходимо сохранить статус выхода.

Это можно сделать довольно легко в bash чтением F в массив с mapfile:

# Invoked as: do_the_work program < F > output
do_the_work() {
  local -a args
  mapfile -t args
  java "$@" "${args[@]}"
}

Возвращение статуса этой функции - это точно возвращение состояния исполняемого файла Java, поэтому вы можете захватить его сразу после вызова:

do_the_work my_program
rc=$?

Для удобства функция также позволяет указывать аргументы в командной строке; оно использует "$@" передать все аргументы командной строки перед передачей аргументов, прочитанных из stdin,

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