我想编写一个脚本,循环遍历 shell 命令的输出(可能是数组?) ps 。
这是命令和输出:
$ 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 脚本中?
原文由 adic26 发布,翻译遵循 CC BY-SA 4.0 许可协议
从不
for循环遍历 shell 命令的结果,如果你想逐行处理它,除非你将 内部字段分隔符$IFS更改为\n。这是因为这些行将成为 分词 的主题,这会导致您看到的实际结果。意思是,例如,如果您有这样的文件:以下for循环
给你:
即使您使用
IFS='\n'这些行仍可能成为 文件名扩展 的主题我建议改用
while+read因为read读取。此外,如果您正在搜索属于某个二进制文件的 pid,我会使用
pgrep。 However, since python might appear as different binaries, likepython2.7orpython3.4I suggest to pass-ftopgrepwhich makes it search the整个命令行,而不仅仅是搜索名为python的二进制文件。但这也会找到已启动的进程,例如cat foo.py。你被警告了!最后,您可以像您希望的那样优化传递给pgrep的正则表达式。例子:
或者如果您还想要进程名称:
如果要将进程名称和 pid 放在单独的变量中:
你看,
read提供了一种灵活稳定的方式来逐行处理命令行的输出。顺便说一句,如果您更喜欢
ps .. | grep命令行而不是pgrep使用以下循环:请注意我如何更改
etime和cmd的顺序。因此,能够将可以包含空格的cmd读入单个变量。这是因为read会将行分解为变量,次数与您指定的变量一样多。该行的其余部分(可能包括空格)将分配给命令行中指定的最后一个变量。