#bash #shell
#bash #оболочка
Вопрос:
Я архивирую и использую split
для создания нескольких частей, одновременно печатая выходные файлы (из split
STDERR, которые я перенаправляю на стандартный вывод). Однако цикл над выходными данными не выполняется до тех пор, пока команда не вернется.
Есть ли в любом случае возможность активного разделения на стандартный вывод команды перед ее возвратом?
Ниже приведено то, что у меня есть в настоящее время, но он выводит список имен файлов только после возврата команды:
export IFS=$'n'
for line in `data_producing_command | split -d -b $CHUNK_SIZE --verbose - $ARCHIVE_PREFIX 2>amp;1`; do
FILENAME=`echo $line | awk '{ print $3 }'`
echo " - $FILENAME"
done
Комментарии:
1. Можете ли вы добавить текущий и ожидаемый результат? или, возможно, перефразируйте вопрос. Не понял, чего вы пытаетесь достичь.
2. Я спрашиваю, как активно разделять и печатать вывод команды, которая постоянно печатается в стандартный вывод. То, что я предоставляю, печатается только после завершения команды.
Ответ №1:
Попробуйте это:
data_producing_command | split -d -b $CHUNK_SIZE --verbose - $ARCHIVE_PREFIX 2>amp;1 | while read -r line
do
FILENAME=`echo $line | awk '{ print $3 }'`
echo " - $FILENAME"
done
Однако обратите внимание, что любые переменные, установленные в while
цикле, не будут сохранять свои значения после цикла ( while
цикл выполняется в подоболочке).
Комментарии:
1. Вы также можете передавать
for
:cat aFileToMakeStdout |for n in $(cat -) ; do echo $n ;done
2. @Leon Никаких изменений. В чем разница в функциях между зацикливанием на неявном выполнении и вызовом «read»?
3. @LinuxDisciple Это, по сути, то, что у меня было.
4. @DustinOprea Во время замены команды (при вызове команды между обратными метками или лучше с использованием рекомендуемого синтаксиса
$(command)
) команда должна завершиться до того, как ее полный вывод будет развернут в сценарий оболочки. В канале элементы канала могут выполняться параллельно.5. @Leon Хотя это исключительный момент, я попробовал оба (а затем попробовал ваш метод). Вот почему странно, что это не сработало.
Ответ №2:
Нет причин для цикла for или чтения или echo. Просто передайте поток в awk:
... | split -d -b $CHUNK_SIZE --verbose - test 2>amp;1 |
awk '{printf " - %sn", $3 }'
Вы увидите некоторую задержку буферизации, но если ваша система не работает очень медленно или вы не очень проницательны, вы вряд ли это заметите.
Ответ №3:
Для выполнения замены команды требуется 1, прежде чем for
цикл может начаться.
for item in $(command which produces items); do ...
в то время как a while read -r
может начать потреблять выходные данные, как только будет создана первая строка (или, что более реалистично, как только выходной буфер заполнится):
command which produces items |
while read -r item; do ...
1 Ну, я полагаю, это не обязательно, с точки зрения дизайна, но именно так это работает в настоящее время.
Как уже отмечал Уильям Перселл, нет особой причины запускать Awk внутри while read
цикла, потому что на самом деле Awk неплохо справляется с этим сам по себе.
command which produces items |
awk '{ print " - " $3 }'
Конечно, с достаточно недавним GNU Coreutils split
вы могли бы просто сделать
split --filter='printf " - %sn" "$FILE"'; cat >"$FILE" ... options