简体   繁体   English

在Bash中拆分和循环实时命令输出

[英]Splitting and looping over live command output in Bash

I am archiving and using split to produce several parts while also printing the output files (from split on STDERR, which I am redirecting to STDOUT). 我正在存档并使用split生成了多个部分,同时还打印了输出文件(来自STDERR上的split ,我将其重定向到STDOUT)。 However the loop over the output data doesn't happen until after the command returns. 但是,直到命令返回后,才对输出数据进行循环。

Is there anyway to actively split over the STDOUT output of a command before it returns? 无论如何,在返回命令之前,是否有必要主动分割STDOUT输出?

The following is what I currently have, but it only prints the list of filenames after the command returns: 以下是我当前拥有的内容,但是仅在命令返回后才显示文件名列表:

export IFS=$'\n'
for line in `data_producing_command | split -d -b $CHUNK_SIZE --verbose - $ARCHIVE_PREFIX 2>&1`; do
    FILENAME=`echo $line | awk '{ print $3 }'`
    echo "    - $FILENAME"
done

Try this: 尝试这个:

data_producing_command | split -d -b $CHUNK_SIZE --verbose - $ARCHIVE_PREFIX 2>&1 | while read -r line
do
    FILENAME=`echo $line | awk '{ print $3 }'`
    echo "    - $FILENAME"
done

Note however that any variables set in the while loop will not preserve their values after the loop (the while loop runs in a subshell). 但是请注意, while循环中设置的任何变量在循环之后都不会保留其值( while循环在子shell中运行)。

There's no reason for the for loop or the read or the echo. 没有理由进行for循环或读取或回显。 Just pipe the stream to awk: 只需将流通过管道传输到awk:

... | split -d -b $CHUNK_SIZE --verbose - test 2>&1 |
 awk '{printf "    - %s\n", $3 }'

You are going to see some delay from buffering, but unless your system is very slow or you are very perceptive, you're not likely to notice it. 您将会看到缓冲的一些延迟,但是除非您的系统非常慢或者您的感知能力很强,否则您不太可能注意到它。

The command substitution needs 1 to run before the for loop can start. 在开始for循环之前,命令替换需要运行1

for item in $(command which produces items); do ...

whereas a while read -r can start consuming output as soon as the first line is produced (or, more realistically, as soon as the output buffer is full): while read -r可以在产生第一行后立即开始消耗输出(或更实际地,在输出缓冲区已满时开始):

command which produces items |
while read -r item; do ...

1 Well, it doesn't absolutely need to, from a design point of view, I suppose, but that's how it currently works. 1好吧,我认为从设计的角度来看并不是绝对必要的 ,但这就是目前的工作方式。

As William Pursell already noted, there is no particular reason to run Awk inside a while read loop, because that's something Awk does quite well on its own, actually. 正如William Pursell已经指出的那样,没有必要在while read循环内运行Awk,因为Awk实际上确实做得很好。

command which produces items |
awk '{ print "    - " $3 }'

Of course, with a reasonably recent GNU Coreutils split , you could simply do 当然,通过最近合理的GNU Coreutils split ,您可以简单地执行

split --filter='printf "   - %s\n" "$FILE"'; cat >"$FILE" ... options

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM