Либо получить исходное возвращаемое значение из 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 $?
Боюсь, вопрос на самом деле не очень понятен, поэтому я сделаю предположения здесь явными:
Файл
F
имеет один аргумент на строку, причем все пробелы, отличные от символов новой строки, являются значимыми, и нет необходимости заменять экранирование обратной косой чертой, например\t
,Вам нужно всего лишь один раз вызвать java-программу со всеми аргументами.
Вам необходимо сохранить статус выхода.
Это можно сделать довольно легко в 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
,