为什么“如果 $(ps aux | grep ...)”在 Bash 中总是成功?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8965509/
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-09 21:32:36  来源:igfitidea点击:

Why "if $(ps aux | grep ...)" always succeeds in Bash?

bashif-statement

提问by Misha Moroshko

Why the following ifstatement succeeds ?

为什么下面的if语句成功?

if $(ps aux | grep -q "bla bla") ; then echo "found" ; fi

回答by SiegeX

Because the grepprocess itself is being returned by ps. You can "trick" grepto not match itself by surrounding one of the search characters in a character class [ ]which doesn't change the functionality: Just do:

因为grep进程本身由ps. 您可以grep通过在[ ]不改变功能的字符类中包围搜索字符之一来“欺骗”以使其不匹配:只需执行以下操作:

if ps aux | grep -q "[b]la bla" ; then echo "found" ; fi

Also, the use of process substitution $()is unnecessary. The ifwill work on the success of the last command in the pipe chain, which is what you want.

此外,$()不需要使用进程替换。在if将在最后一个命令在管道链,这是你想要的成功合作。

Note: The reason the character class trick works is because the psoutput still has the character class brackets but when grepis processing the search string, it uses the brackets as syntax rather than a fixed string to match.

注意:字符类技巧起作用的原因是因为ps输出仍然具有字符类括号,但是在grep处理搜索字符串时,它使用括号作为语法而不是固定字符串进行匹配。

回答by laher

the 'grep' process is already running by the time ps runs, so the ps output includes it.

到 ps 运行时,'grep' 进程已经在运行,因此 ps 输出包含它。

Try using pgrepinstead.

尝试使用pgrep

pgrep is precisely for this purpose:

pgrep 正是为此目的:

if pgrep "bla bla" ; then echo "found" ; fi

if pgrep "bla bla" ; then echo "found" ; fi

回答by Sonic84

If you grep the output from ps aux, you will always get a process showing your previous command. To fix this, you can pipe the output to grep twice, once to remove line with "grep" in it, and again for the process your looking for.

如果您 grep 的输出ps aux,您将始终得到一个显示您之前命令的进程。要解决此问题,您可以将输出通过管道传递给 grep 两次,一次删除其中包含“grep”的行,再次删除您要查找的过程。

ps aux | grep -v "grep" | grep "Finder"

回答by Aaron McDaid

The $(is a small little bit relevant, and changes the meaning a bit. Although in this case, because there is never any output from grep -q, you can just about get away with the $(. You probably want to start with something like (as pointed out by others):

$(是一个小点点相关,并且改变了意思了一下。尽管在这种情况下,因为 从来没有任何输出grep -q,所以您几乎可以摆脱$(. 您可能想从以下内容开始(正如其他人指出的那样):

if ps aux | grep -v 'grep' | grep -q 'bla bla'; then
    echo 'Found'
fi

Anyway, you started with

无论如何,你开始于

if $(ps aux | grep -q "bla bla") ; then echo "found" ; fi

With $(, the command inside the $( )is executed and the output of that command is used as the command line for the outer command. Do these four experiments:

使用$(,执行内部命令,并且该命令$( )的输出用作外部命令的命令行。做这四个实验:

# if $(echo nonexistant ; true) ; then echo "found" ; fi
nonexistant: command not found

# if $(echo nonexistant ; false) ; then echo "found" ; fi
nonexistant: command not found

# if $(echo  ; true) ; then echo "found" ; fi
found

# if $(echo  ; false) ; then echo "found" ; fi

So, according to this you will output get foundif both these conditions hold:

因此,found如果这两个条件都成立,您将根据此输出 get :

  • The command inside the $( )created no output
  • andthe command was succesful
  • $( )创建的命令里面没有输出
  • 并且命令成功

This suggests that ps aux | grep -q "bla bla"was successful and created no output. It's no surprise that grep -qcreates no output. That's what the -qis for. So therefore, your command must have had a true status, which implies that the grep did successfully find a match. We know that grepwill always find a match in this case, because the list of processes from pswill include grepitself; the grep will always find itself.

这表明这ps aux | grep -q "bla bla"是成功的并且没有产生任何输出。不grep -q产生任何输出也就不足为奇了。这就是-q它的用途。因此,您的命令必须具有 true 状态,这意味着 grep 确实成功找到了匹配项。我们知道grep在这种情况下总是会找到匹配项,因为来自的进程列表ps将包含grep自身;grep 总会找到自己。

回答by Johnsyweb

You need to filter out the process that is grepping for 'bla bla':

您需要过滤掉正在grepping 'bla bla'的进程:

$ if ps aux | grep -v 'grep' | grep -q 'bla bla'; then
    echo 'Found'
fi