Home > OS >  Split pipe into two and paste the results together?
Split pipe into two and paste the results together?

Time:12-13

I want to pipe the output of the command into two commands and paste the results together. I found this answer and similar ones suggesting using tee but I'm not sure how to make it work as I'd like it to.

My problem (simplified):

Say that I have a myfile.txt with keys and values, e.g.

key1   /path/to/file1
key2   /path/to/file2

What I am doing right now is

paste \
  <( cat myfile.txt | cut -f1 ) \
  <( cat myfile.txt | cut -f2 | xargs wc -l )

and it produces

key1 23
key2 42

The problem is that cat myfile.txt is repeated here (in the real problem it's a heavier operation). Instead, I'd like to do something like

cat myfile.txt | tee \
  <( cut -f1 ) \
  <( cut -f2 | xargs wc -l ) \
  | paste

But it doesn't produce the expected output. Is it possible to do something similar to the above with pipes and standard command-line tools?

CodePudding user response:

This doesn't answer your question about pipes, but you can use AWK to solve your problem:

$ printf %s\\n 1 2 3 > file1.txt
$ printf %s\\n 1 2 3 4 5 > file2.txt
$ cat > myfile.txt <<EOF
key1    file1.txt
key2    file2.txt
EOF
$ cat myfile.txt | awk '{ ("wc -l " $2) | getline size; sub(/ . $/,"",size); print $1, size }'
key1 3
key2 5

On each line we first we run wc -l $2 and save the result into a variable. Not sure about yours, but on my system wc -l includes the filename in the output, so we strip it with sub() to match your example output. And finally, we print the $1 field (key) and the size we got from wc -l command.

Also, can be done with shell, now that I think about it:

cat myfile.txt | while read -r key value; do
  printf '%s %s\n' "$key" "$(wc -l "$value" | cut -d' ' -f1)"
done

Or more generally, by piping to two commands and using paste, therefore answering the question:

cat myfile.txt | while read -r line; do
  printf %s "$line" | cut -f1
  printf %s "$line" | cut -f2 | xargs wc -l | cut -d' ' -f1
done | paste - -

P.S. The use of cat here is useless, I know. But it's just a placeholder for the real command.

CodePudding user response:

cat myfile.txt | tee >(cut -f1 | xargs -I{} echo {}) >(cut -f2 | xargs wc -l | xargs -I{} echo {}) | paste -d " " - -

  • Related