Использование xargs для назначения stdin переменной - PullRequest
4 голосов
/ 10 августа 2010

Все, что я действительно хочу сделать, это убедиться, что все в конвейере успешно выполнено, и присвоить последний стандартный переменный. Рассмотрим следующий тупой сценарий:

x=`exit 1|cat`

Когда я запускаю declare -a, я вижу это:

declare -a PIPESTATUS='([0]="0")'

Мне нужен какой-то способ заметить exit 1, поэтому я преобразовал его в следующее:

exit 1|cat|xargs -I {} x={}

И declare -a дал мне:

declare -a PIPESTATUS='([0]="1" [1]="0" [2]="0")'

Это то, что я хотел, поэтому я попытался увидеть, что произойдет, если exit 1 не произойдет:

echo 1|cat|xargs -I {} x={}

Но это не с:

xargs: x={}: No such file or directory

Есть ли способ назначить xargs {} на x? А как насчет других методов работы PIPESTATUS и присвоения stdin переменной?

Примечание: эти примеры приведены в тупик. Я на самом деле не делаю exit 1, echo 1 или cat, но использовал эти команды для упрощения, чтобы мы могли сосредоточиться на моей конкретной проблеме.

Ответы [ 5 ]

3 голосов
/ 11 августа 2010

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

Когда вы используете xargs, он ничего не знает о оболочке, поэтому он не может выполнять назначения переменных.

Попробуйте set -o pipefail, тогда вы можете получить статус от $?.

3 голосов
/ 10 августа 2010

xargs запускается в дочернем процессе, как и все команды, которые вы вызываете.Поэтому они не могут влиять на среду вашей оболочки.

Возможно, вы сможете что-то сделать с именованными каналами (mkfifo) или с возможной функцией read bash?

РЕДАКТИРОВАТЬ:

Может быть, просто перенаправить вывод в файл, тогда вы можете использовать PIPESTATUS:

command1 | command2 | command3 >/tmp/tmpfile
## Examine PIPESTATUS
X=$(cat /tmp/tmpfile)
0 голосов
/ 20 ноября 2018

Уже есть несколько полезных решений.Оказывается, у меня на самом деле был пример, который соответствует вопросу, как указано выше;достаточно близко в любом случае .

Учтите это:

 XX=$(ls -l *.cpp | wc -l  | xargs -I{} echo {})
 echo $XX
 3

Это означает, что в моем рабочем каталоге было 3 x .cpp файла.Теперь $XX равно 3, и я могу использовать этот результат в своем скрипте.Это придумано, потому что на самом деле мне не нужен xargs в этом примере.Это работает, хотя.

В примере из вопроса ...

x=`exit 1|cat`

Я не думаю, что это даст вам то, что было указано.exit выйдет из суб-оболочки до того, как cat получит упоминание.Также на этой ноте

Я мог бы начать с чего-то вроде:

declare -a PIPESTATUS='([0]="0")'
x=$?

x теперь имеет статус последней команды.

0 голосов
/ 11 августа 2010

Почему бы просто не заполнить новый массив?

IFS=$'\n' read -r -d '' -a result < <(echo a | cat | cat; echo "PIPESTATUS='${PIPESTATUS[*]}'" )
IFS=$'\n' read -r -d '' -a result < <(echo a | exit 1 | cat; echo "PIPESTATUS='${PIPESTATUS[*]}'" )

echo "${#result[@]}"
echo "${result[@]}"
echo "${result[0]}"
echo "${result[1]}"
0 голосов
/ 11 августа 2010

Как насчет ...

read x <<<"$(echo 1)"
read x < <(echo 1)

echo "$x"
...