Захватить стандартный вывод в переменную и получить статусы выхода трубы переднего плана - PullRequest
3 голосов
/ 07 мая 2020

Я хочу выполнить команду (скажем, ls) и sed ее вывод, а затем сохранить стандартный вывод в переменной, например,

OUT=$(ls | sed -n -e 's/regexp/replacement/p')

После этого, если я попытаюсь получить доступ массив $PIPESTATUS, я получаю только 0 (что совпадает с $?). Итак, как я могу получить как $PIPESTATUS, так и захватить весь стандартный вывод команды по конвейеру? stdout (например, ls | sed -n -e 's/regexp/replacement/p'), я получаю ожидаемые статусы выхода в $PIPESTATUS (например, 0 0)

Если я выполнил только одну команду (без передачи нескольких команд), используя Подстановка команд и захватил стандартный вывод (например, OUT=$(ls)), я ожидаю одиночный статус выхода в $PIPESTATUS (который совпадает с $?)

PS Я знаю, я мог запустить команду 2 раза (сначала для захвата стандартного вывода, затем для доступа к $PIPESTATUS без использования подстановки команд), но есть ли способ получить и то, и другое за один раз?

1 Ответ

2 голосов
/ 07 мая 2020

Вы можете:

  1. Использовать временный файл для передачи PIPESTATUS.

    tmp=$(mktemp)
    out=$(pipeline; echo "${PIPESTATUS[@]}" > "$tmp")
    PIPESTATUS=($(<"$tmp"))  # Note: PIPESTATUS is overwritten each command...
    rm "$tmp"
    
  2. Использовать временный файл для передачи out .

    tmp=$(mktemp)
    pipeline > "$tmp"
    out=$(<"$tmp"))
    rm "$tmp"
    
  3. Выход с чередованием с pipestatus. Например, зарезервируйте часть от последнего символа новой строки до конца для PIPESTATUS. Чтобы сохранить исходный статус возврата, я думаю, необходимы некоторые временные переменные:

    out=$(pipeline; tmp=("${PIPESTATUS[@]}") ret=$?; echo $'\n' "${tmp[@]}"; exit "$ret"))
    pipestatus=(${out##*$'\n'})
    out="${out%$'\n'*}"
    out="${out%%$'\n'}" # remove trailing newlines like command substitution does
    

    протестировано с:

    out=$(false | true | false | echo 123; echo $'\n' "${PIPESTATUS[@]}");
    pipestatus=(${out##*$'\n'});
    out="${out%$'\n'*}"; out="${out%%$'\n'}";
    echo out="$out" PIPESTATUS="${pipestatus[@]}"
    # out=123 PIPESTATUS=1 0 1 0
    

Примечания:

  • Переменные в верхнем регистре по соглашению должны быть зарезервированы для экспортируемых переменных.
...