Bash脚本通过shell输出循环

我想编写一个脚本来循环输出shell命令的输出(可能是数组?):ps命令

这里是在shell命令输出中:

ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh 3089 python /var/www/atm_securit 37:02 17116 python /var/www/atm_securit 00:01 17119 python /var/www/atm_securit 00:01 17122 python /var/www/atm_securit 00:01 17125 python /var/www/atm_securit 00:00 

将其转换成bash脚本(片段):

 for tbl in $(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh) do echo $tbl done 

但是输出成为:

 3089 python /var/www/atm_securit 38:06 17438 python /var/www/atm_securit 00:02 17448 python /var/www/atm_securit 00:01 

我怎么循环像shell输出中的每一行,但在bash脚本?

除非要将内部字段分隔符 $IFS的值更改为\n否则不要循环执行shell命令的结果。 这是因为行将会得到分词的主题,导致你看到的实际结果。 意思是如果你有一个像这样的文件:

 foo bar hello world 

以下为循环

 for i in $(cat file); do echo "$i" done 

给你:

 foo bar hello world 

即使你使用IFS='\n'这些行仍然可能会导致文件名扩展


我建议使用while + read因为read逐行读取。

此外,如果您正在搜索属于某个二进制文件的pid,我会使用pgrep 。 但是,由于python可能会显示为不同的二进制文件,如python2.7python3.4我建议将-f传递给pgrep ,这使得它可以搜索整个命令行,而不是只搜索名为python二进制文件。 但是,这也将找到像cat foo.py一样开始的cat foo.py 。 你被警告了! 最后,您可以按照您的意愿改进传递给pgrep的正则表达式。

例:

 pgrep -f python | while read -r pid ; do echo "$pid" done 

或者如果您还想要进程名称:

 pgrep -af python | while read -r line ; do echo "$line" done 

如果你想在不同的变量中使用进程名称和PID:

 pgrep -af python | while read -r pid cmd ; do echo "pid: $pid, cmd: $cmd" done 

你看, read提供了一个灵活和稳定的方式来处理命令行输出。


顺便说一句,如果你喜欢你的ps .. | grep 通过pgrep ps .. | grep命令行使用以下循环:

 ps -ewo pid,etime,cmd | grep python | grep -v grep | grep -v sh \ | while read -r pid etime cmd ; do echo "$pid $cmd $etime" done 

请注意我是如何改变etimecmd的顺序的。 因此为了能够将可以包含空格的cmd读入到一个变量中。 这是有效的,因为read会将行分解为多个变量。 行的剩余部分 – 可能包括空格 – 将被分配给在命令行中指定的最后一个变量。

当在bash中使用for循环时,默认情况下会使用whitespaces给定的列表,这可以通过使用所谓的内部字段选择器或短IFS

IFS内部字段分隔符,用于扩展后的字词拆分,以及使用读取内置命令将字词拆分为单词。 默认值是“”。

对于您的示例,我们需要告诉IFS使用new-lines作为中断点。

 IFS=$`\n` for tbl in $(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh) do echo $tbl done 

本示例在我的机器上返回以下输出。

  668 /usr/bin/python /usr/bin/ud 03:05:54 27892 python 00:01 

我发现你可以用双引号做这个:

 while read -r proc; do #do work done <<< "$(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh)" 

这将保存每行到数组而不是每个项目。