As you mention, it should be do-able with iterators rather than requiring interprocess pipes. Some idle doodling came up with a syntax that appeals to me and might appeal to you.
# chain_lines takes a list of coderefs
# The first sub in the chain is called with no input; subsequent one
+s are called
# with $_ set to the line from the previous sub; the iterator return
+s one line of
# output from the last sub in the chain. If a sub yields undef, proc
+essing
# restarts at the first sub. When the first sub yields undef, the it
+erator is done.
my $i = chain_lines sub { <$in> },
sub { /^42/ ? $_ : undef }, # grep
sub { join "\t", (split /\t/)[1,3,8] };
# all_lines expands the iterator into a list of lines
sort all_lines($i);
The grep case might warrant its own special syntax, like
grep_lines {/^42/}
Caution: Contents may have been coded under pressure.