我如何循环遍历 shell 命令的输出?
- 2024-10-12 10:28:00
- admin 原创
- 76
问题描述:
我想编写一个脚本,循环遍历 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 脚本中循环遍历每一行?
解决方案 1:
如果您想逐行处理 shell 命令的结果,切勿for
循环处理,除非您将内部字段分隔符 $IFS
的值更改为`
`。这是因为这些行将受到分词的影响,从而导致您看到的实际结果。这意味着如果您有这样的文件:
foo bar
hello world
以下 for 循环
for i in $(cat file); do
echo "$i"
done
给你:
foo
bar
hello
world
即使你使用`IFS='
'`行可能仍然会得到文件名扩展的主题
我建议使用while
+read
因为read
它可以逐行读取。
pgrep
此外,如果您要搜索属于某个二进制文件的 pid,我会使用。但是,由于 python 可能显示为不同的二进制文件,例如python2.7
或python3.4
我建议传递-f
给它pgrep
,这使它搜索整个命令行,而不仅仅是搜索名为的二进制文件python
。但这也会找到已启动的进程,例如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 -ewo pid,etime,cmd | grep python | grep -v grep | grep -v sh \ n | while read -r pid etime cmd ; do
echo "$pid $cmd $etime"
done
etime
注意我如何更改和的顺序cmd
。这样就可以将cmd
可能包含空格的读入单个变量。这样做是因为它read
将该行分解为变量,次数与您指定的变量相同。该行的剩余部分(可能包括空格)将分配给命令行中指定的最后一个变量。
解决方案 2:
我发现只需使用双引号就可以做到这一点:
while read -r proc; do
#do work
done <<< "$(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh)"
这会将每一行保存到数组中,而不是每个项目。
解决方案 3:
在 bash 中使用for
循环时,它默认通过 来拆分给定的列表,这可以通过使用所谓的内部字段分隔符(简称 )whitespaces
来进行调整。IFS
IFS 内部字段分隔符,用于扩展后的单词分割以及使用内置命令 read 将行分割为单词。默认值为“”。
对于您的示例,我们需要告诉IFS
将new-lines
其用作断点。
IFS=$'
'
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
解决方案 4:
这是另一个基于 bash 的解决方案,受到@Gordon Davisson的评论的启发。
为此,我们需要(至少 bash v1.13.5 (1992)或更高版本),因为使用了Process-Substitution2、3、4等。 while read var; do { ... }; done < <(...);
#!/bin/bash
while IFS= read -a oL ; do { # reads single/one line
echo "${oL}"; # prints that single/one line
};
done < <(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh);
unset oL;
注意:您可以在其中使用任何简单或复杂的命令/命令集,<(...)
其中可能有多条输出行。这里
显示了哪段代码执行什么功能。
这是一个单一/单行的方式:
while IFS= read -a oL ; do { echo "${oL}"; }; done < <(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh); unset oL;
(由于 Process-Substitution 尚不是 POSIX 的一部分,因此许多符合 POSIX 的 shell 或 bash-shell 的 POSIX shell 模式都不支持它。 Process-Substitution 自 1992 年以来就存在于 bash 中(所以从现在起/2020 年是 28 年前),并且存在于 ksh86(1985 年之前)1中。所以 POSIX 应该将它包含在内。)
如果您或任何用户想要在符合 POSIX 的 shell 中使用类似于 Process-Substitution 的东西(即:sh、ash、dash、pdksh/mksh 等),请查看NamedPipes。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件