将输出重定向到两个进程并合并

时间:2012-03-23 20:46:15

标签: bash

背景:有时我使用ps aux | grep process_name来计算流程的一些统计信息。但我不记得ps输出的标题。所以我需要这样做:

ps aux | tee 1.txt | grep process_name > 2.txt
cat 1.txt | head -1 | cat - 2.txt

所以我的问题是:有没有办法在没有两个临时文件的情况下实现这一点,最好使用一行命令而不是两行?

6 个答案:

答案 0 :(得分:2)

最简单的方法就是使用比grep更聪明的东西。例如:

ps aux | perl -ne 'print if $. == 1 || m/process_name/'

将打印ps aux输出的第一行,以及匹配process_name的任何行(这是一个Perl正则表达式 - 比POSIX BRE更强大,因此更复杂,但我不喜欢如果您只是在搜索流程名称,我认为您会发现任何意外。

编辑添加:就此而言,由于ps aux的标题在运行之间不太可能发生变化,您可以写一下:

ps aux | head -1 ; ps aux | grep process_name

虽然我不知道这是否仍然算作“一行命令”。 : - )

更多选项:由于您不喜欢上述内容,此处还有更多内容。这个将直接读取并打印第一行,然后留下grep的其余部分来阅读和处理:

ps aux | ( ( read -r LINE ; echo "$LINE" ) ; grep process_name )

这一行将导致每一行都写入标准输出(文件描述符1)和自定义文件描述符(3);然后head获得标准输出,而grep获取写入自定义文件描述符的内容:

( ( ps aux | while read -r LINE ; do echo "$LINE" ; echo "$LINE" 1>&3 ; done | head -1 1>&4 ) 3>&1 | grep process_name ) 4>&1

这是我所知道的最常用的方式来做你所要求的 - 至少,只使用Bash内置和功能 - 但正如你所看到的,这是非常笨重的,这就是为什么我建议更简单当你不需要这种方法的全部功能时。而且,最后一个不再保证标头首先出现;在我的系统上,head的输出似乎始终在 grep的输出之后结束。 (我想这可以通过交换headgrep命令的位置来解决,但据我所知,这仍然不可靠,当我尝试时它似乎有奇怪的效果它刚才。)

答案 1 :(得分:1)

或者,因为我不记得perl或awk而没有查找它:

ps aux | head -n 1 && ps aux |grep process_name

答案 2 :(得分:1)

另一个肮脏的技巧是记住标题以'USER'开头并执行

ps aux | grep -E 'USER | process_name'

这也将显示grep命令本身:)

答案 3 :(得分:1)

或者

ps aux | egrep "(^USER +PID)|^process_name"

答案 4 :(得分:1)

sed将完全符合您的要求:

ps aux | sed -n -e '1 p; /PROCESS_NAME/p'

sed命令行:

-n仅打印指定的行
-e执行以下脚本
1 p打印第一行
;命令分隔符
/PROCESS_NAME/p打印包含PROCESS_NAME

的行

答案 5 :(得分:1)

使用-C

的进程名称
ps u -C java -C totem
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
stefan   16878  0.1 10.5 429036 107868 pts/7   Sl+  12:51   0:24 /opt/java/bin/java -Xmx256M -Xms32M -Xbootclasspa
stefan   25791  0.5  3.8 202800 38984 ?        Sl   17:45   0:16 totem file:///home/stefan/Desktop/scala/dritte/dl

我希望这不仅适用于Linux。 :)

我总是很困惑地看到,有多少人不知道(或使用) ps 的选项 - 也许有太多?它总是ps | grep x。 :)