通过分流,我的意思是能够:
- 通过第一个函数动态过滤流内容
- 流的一部分由第二个函数处理
- 流的其余部分由第三个函数处理
- 流永远不会存储(在运行中)
一个例子有时比一个冗长的解释更好。此命令行使用tee和处理替换来拆分流:
$> cut -f2 file | tee >( grep "AB" | sort | ... ) | grep -v "AB" | tr A B | ...
在这个例子中,流被分成两部分:包含的行"AB"和其余的:
cut -f2 file ---->- line contains "AB" ->- sort ->- ...
             \--->- does not contain "AB" ->- tr A B ->- ...
但我不喜欢这种流拆分技术,因为流首先被复制(by tee)然后被过滤两次(bygrep和grep -v)。
因此,我想知道在perl、python、ruby 、c++等其他语言中是否有类似流拆分的东西......
我在下面提供了一个更复杂的示例。
复杂bash的分流
counter.sh将流分成三个部分(开始、中间和结束)。对于每个部分,流再次被拆分以计算符号的出现次数<,|和>:
#!/bin/bash    
{
  {  tee >( sed -n '1,/^--$/!p' >&3 ) |
            sed -n '1,/^--$/p'        |
     tee >( echo "del at begin:  $(grep -c '<')"    >&4 ) |
     tee >( echo "add at begin:  $(grep -c '>')"    >&4 ) |
          { echo "chg at begin:  $(grep -c '|')"; } >&4
  }  3>&1 1>&2  |
  {  tee >( sed -n '/^--$/,/^--$/!p' >&3 ) |
            sed -n '/^--$/,/^--$/p'        |
     tee >( echo "del at end:    $(grep -c '<')"    >&4 ) |
     tee >( echo "add at end:    $(grep -c '>')"    >&4 ) |
          { echo "chg at end:    $(grep -c '|')"; } >&4
  }  3>&1 1>&2 |
     tee >( echo "del in middle: $(grep -c '<')"    >&4 ) |
     tee >( echo "add in middle: $(grep -c '>')"    >&4 ) |
            echo "chg in middle: $(grep -c '|')"; 
} 4>&1
此脚本用于计算开始/中间/结束部分中添加/更改/删除的行数。这个脚本的输入是一个流:
$> cat file-A
1
22
3
4
5
6
77
8
$> cat file-B
22
3
4
42
6
77
8
99
$> diff --side-by-side file-A file-B | egrep -1 '<|\||>' | ./counter.sh
del at begin:  1
add at begin:  0
chg at begin:  0
del at end:    0
add at end:    1
chg at end:    0
del in middle: 0
add in middle: 0
chg in middle: 1
counter.sh如何在不将数据存储在临时缓冲区中的情况下在其他编程语言中有效地实现此类?
回答
正如Lennart Regebro所指出的,我在想这个问题。当然,所有这些语言都能够按照ysth的回答拆分输入流。在伪代码中:
while input-stream
{
    case (begin section)
    {
        case (symbol <) aB++ 
        case (symbol |) cB++ 
        case (symbol >) dB++
    }
    case (middle section)
    {
        case (symbol <) aM++ 
        case (symbol |) cM++ 
        case (symbol >) dM++
    } 
    case (ending section)
    {
        case (symbol <) aE++ 
        case (symbol |) cE++ 
        case (symbol >) dE++
    }
}
PrintResult (aB, cB, dB, aM, cM, dM, aE, cE, dE)