Использование xargs для присвоения stdin переменной

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

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, но использовал эти команды для упрощения, чтобы мы могли сосредоточиться на моей конкретной проблеме.


person User1    schedule 10.08.2010    source источник


Ответы (6)


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

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

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

person Dennis Williamson    schedule 10.08.2010
comment
pipefail - хороший вариант для рассмотрения. Тем не менее, я хотел бы получить PIPESTATUS за все, что находится в стадии разработки. - person User1; 11.08.2010

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

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

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

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

command1 | command2 | command3 >/tmp/tmpfile
## Examine PIPESTATUS
X=$(cat /tmp/tmpfile)
person Douglas Leeder    schedule 10.08.2010
comment
Я думал, что чтение может делать что-то подобное. echo 1 | чтение x не сработало. У вас есть пример? - person User1; 10.08.2010

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

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

echo "$x"
person timo    schedule 10.08.2010
comment
Интересная мысль. Использование (exit 1 | cat) по-прежнему не заполняет PIPESTATUS должным образом. - person User1; 11.08.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]}"
person timo    schedule 11.08.2010

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

Учти это:

 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 теперь имеет статус последней команды.

person will    schedule 20.11.2018

Назначьте каждую строку ввода массиву, например все файлы python в каталоге

declare -a pyFiles=($(ls -l *.py | awk '{print $9}')) 

где $ 9 - девятое поле в ls -l, соответствующее имени файла

person TRicks43    schedule 17.12.2019