bash 基本名称或以 awk 结尾?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9424888/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 01:38:54  来源:igfitidea点击:

basename or endswith in awk?

bashawk

提问by tony19

I'm using awkto get the pidof a specific process by name.

我正在使用按名称awk获取pid特定进程的。

#!/bin/sh

for pid in $(ps | awk ' == "foo" { print  }')
do
    i=1
    echo "killing foo at pid $pid"
    kill $pid && echo 'ok' || echo 'failed'
done

where psoutput on OSX is something like:

psOSX上的输出类似于:

$ ps
  PID TTY           TIME CMD
 1858 ttys000    0:00.15 -bash
 4148 ttys000    0:01.37 /a/b/c/foo

but my shell script only works if the process in the CMDcolumn is exactly foo(no absolute paths).

但我的 shell 脚本仅在CMD列中的进程完全正确foo(没有绝对路径)时才有效。

I'm thinking I can use basename, but how do I call it from awk?
OR
Is there something like $4.endswith('foo')in awk?

我想我可以使用basename,但我如何调用它awk
或者
有什么样$4.endswith('foo')awk

回答by Dan Fego

awkcan use regular expressions. So rather than $4 == "foo", you could do something like:

awk可以使用正则表达式。因此$4 == "foo",您可以执行以下操作:

awk ' ~ /\/foo$/ { print  }'

The regular expression is between the /and /. \/foo$says "a backslash followed by foo and then the end of the field." In this case, your field is /a/b/c/foo, so it would match.

正则表达式介于/和之间/\/foo$说“反斜杠后跟 foo 然后是字段的结尾。” 在这种情况下,您的字段是/a/b/c/foo,因此它将匹配。

回答by minopret

In addition to regular expressions, you can use string manipulation as substr($4, length($4) - 2) == "foo".

除了正则表达式,您还可以使用字符串操作作为substr($4, length($4) - 2) == "foo".

回答by David W.

First of all, you should use a while readconstruct instead of for. With a forloop, you have to wait for the command in the $(...)to execute before the for loop can start. Plus, you couldoverrun the command buffer. Not a major issue today, but when you run into it, you'll never get any indication that something went wrong:

首先,您应该使用while read构造而不是for. 对于for循环,您必须等待$(...)for 循环开始之前执行中的命令。另外,您可能会溢出命令缓冲区。今天不是一个大问题,但是当你遇到它时,你永远不会得到任何出错的迹象:

ps | awk ' == "foo" { print  }' | while read pid
do
    i=1
    echo "killing foo at pid $pid"
    kill $pid && echo 'ok' || echo 'failed'
done

Nothing much to do with your problem, but I need to get that off my chest.

与你的问题没什么关系,但我需要把它从我的胸膛中解脱出来。



Now on to your Answer:

现在回答你的问题:

The awkautomatically does a loop, so since you're using awkanyway, why not let it do the work for you? Most awkimplementations have a systemcommand, so you can execute the killright inside your awkscript.

awk自动完成一个循环,这样以来你使用awk,无论如何,为什么不让它为你做的工作?大多数awk实现都有一个system命令,因此您可以killawk脚本中执行正确的操作。

Also, take a look at man psand check your PS options. Most ps command take the -ooption which allows you to specify which fields to print. My pscommand (which just happens to be on OS X) allows you to use ucommwhich is just the name of the command without the directory or the command line parameters. Sounds useful for your situation. I'll use ps -opid, ucommwhich will print only two columns for the pscommand: The PID, and the command name sans directory and command line parameters:

另外,请查看man ps并检查您的 PS 选项。大多数 ps 命令采用-o允许您指定要打印的字段的选项。我的ps命令(恰好在 OS X 上)允许您使用ucommwhich 只是命令的名称,而没有目录或命令行参数。听起来对你的情况很有用。我将使用ps -opid, ucommwhich 将只打印ps命令的两列:PID,以及命令名称 sans 目录和命令行参数:

$ ps -o pid,ucomm
  PID UCOMM
    1 launchd         
   10 kextd           
   11 UserEventAgent  
   12 mDNSResponder   
   13 opendirectoryd  
   14 notifyd         
   15 fseventsd       
   16 configd         
   17 diskarbitrationd
   18 syslogd         

(Just one warning, it looks like ucommcuts things off at the 14th or 16th column. Just to let you know).

(只是一个警告,它看起来像是ucomm在第 14 或 16 列切断了东西。只是为了让你知道)。

For awk, we can use the -vparameter to define an Awk variable. This is useful in case you write a shell script, and want awk to take the name of the program from the command parameters.

对于awk,我们可以使用-v参数来定义一个 Awk 变量。这在您编写 shell 脚本并希望 awk 从命令参数中获取程序名称的情况下很有用。

In Awk, as you know, $1 will represent the PID and $2 will represent the command sans the directory or command line parameters.

在 Awk 中,如您所知,$1 将代表 PID,$2 将代表没有目录或命令行参数的命令。

We can use the $2 == commandto filter out all the lines in your pscommand where the command is foo. This is a shortcut to the ifstatement.

我们可以使用$2 == command来过滤掉ps命令中命令所在的所有行foo。这是if语句的快捷方式。

And, most implementations of awkhave a systemfunction which can be used to run commands like killfrom inside your awkscript. Looks like we have almost everything we need:

而且,大多数实现awk都有一个system函数,可用于killawk脚本内部运行命令。看起来我们几乎拥有我们需要的一切:

ps -o pid,ucomm | awk -v command="foo" ' == command {system("kill " )}'

That's a nice clean one liner, but it doesn't check the status of the system command, nor does it echo out when it fails or what command and PID you're killing.

这是一个非常干净的衬垫,但它不会检查系统命令的状态,也不会在它失败时或您正在杀死的命令和 PID 时回显出来。

Good thing that Awk isn't just an abstruse command. It's also an abstruse programming language. We could test the return of the systemcommand and add a few print statements. I didn't test this, but it should be pretty close:

好在 Awk 不仅仅是一个深奥的命令。它也是一种深奥的编程语言。我们可以测试system命令的返回并添加一些打印语句。我没有测试这个,但它应该非常接近:

ps -o pid,ucomm | awk -v command="foo" ' == command {
   print "Killing "  " at PID " 
   if (system("kill " )) {
       print "Failed to kill PID " 
   }
}'

The ifmay have to be if (! system("kill " $1)) {instead.

if可能要if (! system("kill " $1)) {代替。

回答by Adam Liss

For the condition, you can use

对于条件,您可以使用

 ~ /\/foo$/

which translates to "the 4th field matches an (escaped) forward-slash followed by 'foo' at the end of the line."

转换为“第 4 个字段匹配(转义的)正斜杠,后跟行尾的 'foo'。”

回答by Hai Vu

It seems you are trying to kill all processes which has name 'foo', how about:

您似乎正在尝试杀死所有名为“foo”的进程,如何:

killall foo

回答by Javier López

When looking for pids, you must exclude the awk process, otherwise it could kill the search process instead.

在查找 pid 时,您必须排除 awk 进程,否则它可能会杀死搜索进程。

kill $(ps -aef | awk -v program="mplayer" '##代码## ~ program {if (##代码## !~ "awk") print }')