我想编写一个脚本来循环输出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.7
或python3.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
请注意我是如何改变etime
和cmd
的顺序的。 因此为了能够将可以包含空格的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)"
这将保存每行到数组而不是每个项目。