dhr*_*hrm 6 macos bash awk grep
我正在尝试创建一个shell脚本,在我的Mac上获取Skype应用程序的进程ID.
ps -clx | grep'Skype'| awk'{print $ 2}'| 头-1
以上工作正常,但有两个问题:
1) 如果grep命令名称只包含"Skype",则会获得所有进程.如果进程名称恰好是Skype,我怎样才能确保它只获得结果?
2) 我想从中创建一个shell脚本,可以从终端使用,但进程名称应该是此脚本的参数:
#!/bin/sh
ps -clx | grep '$1' | awk '{print $2}' | head -1
Run Code Online (Sandbox Code Playgroud)
这不会返回任何东西.我认为这是因为awk中的$ 2也被视为一个参数.我怎么解决这个问题?
Dav*_* W. 14
您的ps -cl1
输出如下所示:
UID PID PPID F CPU PRI NI SZ RSS WCHAN S ADDR TTY TIME CMD
501 185 172 104 0 31 0 2453272 1728 - S ffffff80145c5ec0 ?? 0:00.00 httpd
501 303 1 80004004 0 31 0 2456440 1656 - Ss ffffff8015131300 ?? 0:11.78 launchd
501 307 303 4004 0 33 0 2453456 7640 - S ffffff8015130a80 ?? 0:46.17 distnoted
501 323 303 40004004 0 33 0 2480640 9156 - S ffffff80145c4dc0 ?? 0:03.29 UserEventAgent
Run Code Online (Sandbox Code Playgroud)
因此,每行中的最后一个条目是您的命令.这意味着您可以使用正则表达式的全部功能来帮助您.
该$
正则表达式表示字符串的结尾,因此,你可以使用$
指定不仅输出必须Skype
在它,它必须结束Skype
.这意味着如果你有一个被调用的命令Skype Controller
,你就不会把它拉起来:
ps -clx | grep 'Skype$' | awk '{print $2}' | head -1
Run Code Online (Sandbox Code Playgroud)
您还可以使用ps -o
格式简化事项,只需提取所需的列:
ps -eo pid,comm | grep 'Skype$' | awk '{print $1}' | head -1
Run Code Online (Sandbox Code Playgroud)
而且,您可以head
通过简单地使用awk
为您选择行的能力来消除.在awk
,NR
是你的记录号码.因此你可以这样做:
ps -eo pid,comm | grep 'Skype$' | awk 'NR == 1 {print $1}'
Run Code Online (Sandbox Code Playgroud)
哎呀,既然我想到了,我们也可以消除它grep
:
ps -eo pid,comm | awk '/Skype$/ {print $1; exit}'
Run Code Online (Sandbox Code Playgroud)
这是使用awk使用正则表达式的能力.如果该行包含正则表达式'Skype $',它将打印第一列,然后退出
唯一的问题是如果你有一个命令Foo Skype
,这也会捡起它.要消除这种情况,你必须做更多花哨的步法:
ps -eo pid,comm | while read pid command
do
if [[ "$command" = "Skype" ]]
then
echo $pid
break
fi
done
Run Code Online (Sandbox Code Playgroud)
该while read
是读书的两个变量.诀窍是read
使用空格来划分它读入的变量.但是,由于只有两个变量,最后一个变量将包含整个行的其余部分.因此,如果该命令是Skype控制器,$command
即使其中有空格,也将放入整个命令.
现在,我们不必使用正则表达式.我们可以将命令与相等进行比较.
输入时间较长,但实际上您使用的命令更少,管道更少.记住awk
循环遍历每一行.你在这里所做的只是让它更明确.最后,这实际上比你原来的效率要高得多.