我想编写一个脚本来循环输出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
Run Code Online (Sandbox Code Playgroud)
将其转换为bash脚本(Snippet):
for tbl in $(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh)
do
echo $tbl
done
Run Code Online (Sandbox Code Playgroud)
但输出变为:
3089
python
/var/www/atm_securit
38:06
17438
python
/var/www/atm_securit
00:02
17448
python
/var/www/atm_securit
00:01
Run Code Online (Sandbox Code Playgroud)
如何在shell输出中循环遍历每一行,但是在bash脚本中?
hek*_*mgl 31
for如果要逐行处理shell命令,切勿循环遍历shell命令的结果,除非您要将内部字段分隔符 的值更改$IFS为\n.这是因为线条将成为分词的主题,这会导致您看到的实际结果.例如,如果你有一个像这样的文件的意思:
foo bar
hello world
Run Code Online (Sandbox Code Playgroud)
以下for循环
for i in $(cat file); do
echo "$i"
done
Run Code Online (Sandbox Code Playgroud)
给你:
foo
bar
hello
world
Run Code Online (Sandbox Code Playgroud)
即使您使用IFS='\n'这些行仍然可能会受到文件名扩展的影响
我建议使用while+ read代替,因为read逐行读取.
此外,pgrep如果您正在搜索属于某个二进制文件的pids,我会使用.但是,因为python可能看起来像不同的二进制文件,python2.7或者python3.4我建议传递-f给pgrep它,这使得它搜索整个命令行而不是仅搜索被调用的二进制文件python.但是这也会找到已经开始的过程cat foo.py.你被警告了!最后,您可以根据pgrep自己的意愿优化传递的正则表达式.
例:
pgrep -f python | while read -r pid ; do
echo "$pid"
done
Run Code Online (Sandbox Code Playgroud)
或者如果您还想要进程名称:
pgrep -af python | while read -r line ; do
echo "$line"
done
Run Code Online (Sandbox Code Playgroud)
如果您希望进程名称和pid在单独的变量中:
pgrep -af python | while read -r pid cmd ; do
echo "pid: $pid, cmd: $cmd"
done
Run Code Online (Sandbox Code Playgroud)
您可以看到,它read提供了一种灵活而稳定的方法来逐行处理命令的输出.
顺便说一句,如果您更喜欢ps .. | grep命令行,请pgrep使用以下循环:
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
Run Code Online (Sandbox Code Playgroud)
请注意我是如何改变的秩序etime和cmd.因此,能够将cmd包含空格的内容读入单个变量中.这是有效的,因为read会将行分解为变量,与指定变量一样多.该行的剩余部分 - 可能包括空格 - 将被分配给在命令行中指定的最后一个变量.
我发现你可以做到这一点,只需使用双引号:
while read -r proc; do
#do work
done <<< "$(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh)"
Run Code Online (Sandbox Code Playgroud)
这会将每一行保存到数组而不是每个项目。
for在 bash 中使用循环时,它默认将给定的列表拆分为whitespaces,这可以通过使用所谓的内部字段分隔符进行调整,或者IFS简而言之。
IFS 内部字段分隔符,用于在扩展后进行分词,并使用 read 内置命令将行拆分为单词。默认值为“”。
为了您的例子中,我们需要告诉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
Run Code Online (Sandbox Code Playgroud)
此示例在我的机器上返回以下输出。
668 /usr/bin/python /usr/bin/ud 03:05:54
27892 python 00:01
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
34947 次 |
| 最近记录: |