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 " " - -