简体   繁体   English

在shell(bash)中如何在管道中执行多个命令?

[英]In a shell (bash) How can I execute more than one command in a pipeline?

I'm trying pipe the output of an awk command through more than one command at once in a Bash shell, following my knowledge I'm coming up with this: 我正在尝试在Bash shell中同时通过多个命令输出awk命令的输出,据我所知,我想出了这个:

awk '$13 ~ /type/ {print $15}' filename.txt | (wc -l || sort -u)

I want the result of the awk command to be both counted AND sorted, how can I accomplish that? 我希望awk命令的结果都被计算和排序,我该如何实现? Even with && command it doesn't work, it does execute the first command and then exits. 即使使用&&命令它也不起作用,它会执行第一个命令然后退出。 I guess it is my knowledge of bash which is failing. 我想这是我对bash失败的了解。

Thanks in advance. 提前致谢。

If you want to send output to two different commands in a single line, you'll need to do process substituion. 如果要在一行中将输出发送到两个不同的命令,则需要进行过程替换。

Try this: 尝试这个:

awk '$13 ~ /type/ {print $15}' filename.txt | tee >(wc -l >&2) | sort -u

This outputs the line count on stderr and the sorted output on stdout. 这将输出stderr上的行数和stdout上的已排序输出。 If you need the line count on stdout, you can do that leave off the >&2 , but then it will be passed to the sort call and (most likely) sorted to the top of the output. 如果你需要stdout上的行数,你可以这样做,不用>&2 ,但是它会传递给sort调用,并且(最有可能)排序到输出的顶部。

EDIT: corrected description of what happens based on further testing. 编辑:纠正了基于进一步测试发生的事情的描述。

in that case, do your counting in awk , why the need for pipes? 在那种情况下,你在awk中计算,为什么需要管道? don't make it more complicated 不要让它变得更复杂

awk '$13 ~ /type/ {print $15;c++}END{print c} ' filename.txt | sort -u

If the size in the output is not too large to fit in memory and you don't need the wc and sort commands to work in parallel for performance reasons, here's a relatively simple solution: 如果输出中的大小不是太大而不适合内存而且由于性能原因你不需要wcsort命令并行工作,这里有一个相对简单的解决方案:

output=$(awk '$13 ~ /type/ {print $15}' filename.txt; echo a)
printf "%s" "${output%a}" | sort -u
printf "%s" "${output%a}" | wc -l

That complication with the the extra a is in case the awk command might print some empty lines at the end of the input, which the $() construct would strip. 如果awk命令可能在输入的末尾打印一些空行,则$()构造将剥离,这与额外的a复杂化。 You can easily choose which of sort or wc should appear first. 您可以轻松选择首先出现的sortwc


Here's a way that works with any POSIX shell (ash, bash, ksh, zsh, ...) but only on systems that have /dev/fd (which includes reasonably recent Linux, *BSD and Solaris). 这是一种适用于任何POSIX shell(ash,bash,ksh,zsh,...)的方法,但仅适用于具有/dev/fd (包括合理的Linux,* BSD和Solaris)的系统。 Like Walter's similar construction using the simpler method available in bash, ksh93 and zsh , the output of wc and the output of sort may be intermixed. 就像Walter使用bash,ksh93和zsh中可用的更简单方法的类似结构一样, wc的输出和sort的输出可以混合。

{
  awk '$13 ~ /type/ {print $15}' filename.txt |
  tee /dev/fd3 |
  wc -l
} 3>&1 1>&3 | sort -u

If you both need to deal with intermediate output that doesn't comfortably fit in memory and don't want to have the output of the two commands intermixed, I don't think there's an easy way in a POSIX shell, though it should be doable with ksh or zsh coprocesses. 如果你们都需要处理不适合内存的中间输出并且不希望将两个命令的输出混合在一起,我认为在POSIX shell中有一种简单的方法,尽管它应该是可以使用ksh或zsh coprocesses。

I think the bigger question is: what are you expecting the output to be? 我认为更大的问题是:你对输出的期望是什么?

If you're trying to do two things, then do two things: 如果你想做两件事,那么做两件事:

awk '$13 ~ /type/ {print $15}' filename.txt > tempfile
wc -l < tempfile
sort -u < tempfile
rm tempfile

You want to use named pipes created with mkfifo in combination with tee. 您希望将使用mkfifo创建的命名管道与tee结合使用。 An example is at http://www.softpanorama.org/Tools/tee.shtml 一个例子是http://www.softpanorama.org/Tools/tee.shtml

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

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