shell 我如何否定一个进程的返回值?

zz2j4svz  于 2023-08-07  发布在  Shell
关注(0)|答案(7)|浏览(127)

我正在寻找一个简单的,但跨平台的 negate-进程,否定一个进程返回的值。它应该将0Map到某个值!= 0和任意值!= 0至0,即下面的命令应该返回“yes,nonexistingpath doesn 't exist”:

ls nonexistingpath | negate && echo "yes, nonexistingpath doesn't exist."

字符串
!-操作符很棒,但不幸的是它不是独立于shell的。

e0uiprwp

e0uiprwp1#

  • 以前,答案是以现在的第一部分作为最后一部分。*

POSIX Shell包含!运算符

我最近(2015年9月)注意到POSIX shell支持!运算符。例如,它被列为保留字,可以出现在管道的开始处-其中简单命令是“管道”的特殊情况。因此,它也可以在if语句和whileuntil循环中使用-在POSIX兼容的shell中。因此,尽管我有所保留,但它可能比我在2008年意识到的更广泛。对POSIX 2004和SUS/POSIX 1997的快速检查表明,这两个版本中都存在!
请注意,!运算符必须出现在管道的 * 开头 *,并对整个管道的状态码取反(即 last 命令)。以下是一些例子。

# Simple commands, pipes, and redirects work fine.
$ ! some-command succeed; echo $?
1
$ ! some-command fail | some-other-command fail; echo $?
0
$ ! some-command < succeed.txt; echo $?
1

# Environment variables also work, but must come after the !.
$ ! RESULT=fail some-command; echo $?
0

# A more complex example.
$ if ! some-command < input.txt | grep Success > /dev/null; then echo 'Failure!'; recover-command; mv input.txt input-failed.txt; fi
Failure!
$ ls *.txt
input-failed.txt

字符串

便携式答案-适用于古董 shell

在Bourne(Korn,POSIX,Bash)脚本中,我用途:

if ...command and arguments...
then : it succeeded
else : it failed
fi


这是便携式的,因为它得到。“命令和参数”可以是流水线或其他复合命令序列。

not命令

'!'操作符,无论是内置在shell中还是由o/s提供,都不是通用的。这并不是很难写,虽然-下面的代码可以追溯到至少1991年(虽然我认为我写了一个更早的版本甚至更早)。不过,我不倾向于在脚本中使用它,因为它并不可靠。

/*
@(#)File:           $RCSfile: not.c,v $
@(#)Version:        $Revision: 4.2 $
@(#)Last changed:   $Date: 2005/06/22 19:44:07 $
@(#)Purpose:        Invert success/failure status of command
@(#)Author:         J Leffler
@(#)Copyright:      (C) JLSS 1991,1997,2005
*/

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "stderr.h"

#ifndef lint
static const char sccs[] = "@(#)$Id: not.c,v 4.2 2005/06/22 19:44:07 jleffler Exp $";
#endif

int main(int argc, char **argv)
{
    int             pid;
    int             corpse;
    int             status;

    err_setarg0(argv[0]);

    if (argc <= 1)
    {
            /* Nothing to execute. Nothing executed successfully. */
            /* Inverted exit condition is non-zero */
            exit(1);
    }

    if ((pid = fork()) < 0)
            err_syserr("failed to fork\n");

    if (pid == 0)
    {
            /* Child: execute command using PATH etc. */
            execvp(argv[1], &argv[1]);
            err_syserr("failed to execute command %s\n", argv[1]);
            /* NOTREACHED */
    }

    /* Parent */
    while ((corpse = wait(&status)) > 0)
    {
            if (corpse == pid)
            {
                    /* Status contains exit status of child. */
                    /* If exit status of child is zero, it succeeded, and we should
                       exit with a non-zero status */
                    /* If exit status of child is non-zero, if failed and we should
                       exit with zero status */
                    exit(status == 0);
                    /* NOTREACHED */
            }
    }

    /* Failed to receive notification of child's death -- assume it failed */
    return (0);
}


当执行命令失败时,返回“success”,与“failure”相反。我们可以讨论“成功地什么都不做”的选择是否正确;也许它应该在没有被要求做任何事情的时候报告一个错误。'"stderr.h"'中的代码提供了简单的错误报告功能-我在任何地方都使用它。源代码的要求-看到我的个人资料页与我联系。

cqoc49vn

cqoc49vn2#

在Bash中,使用!操作员在命令之前。例如:

! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist"

字符串

mbzjlibv

mbzjlibv3#

您可以尝试:

ls nonexistingpath || echo "yes, nonexistingpath doesn't exist."

字符串
或者只是:

! ls nonexistingpath

inkz8wg9

inkz8wg94#

如果你没有使用Bash作为shell(例如:Git脚本或Puppet exec测试),您可以运行:
第一个月
-> retcode:0
echo '! ls /' | bash
-> retcode:1

kmbjn2e3

kmbjn2e35#

解决方案没有!,不带subshell,不带if,并且应该至少在Bash中工作:

ls nonexistingpath; test $? -eq 2 && echo "yes, nonexistingpath doesn't exist."

# Alternatively without an error message and handling of any error code > 0
ls nonexistingpath 2>/dev/null; test $? -gt 0 && echo "yes, nonexistingpath doesn't exist."

字符串

oogrdqng

oogrdqng6#

! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist."

字符串
或者是

ls nonexistingpath || echo "yes, nonexistingpath doesn't exist."

rur96b6h

rur96b6h7#

注意:有时你会看到!(command || other command)
这里! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist."就足够了。
不需要子shell。
Git 2.22(2019年第二季度)通过以下方式说明了更好的形式:
Commit 74ec8cfcommit 3fae7adcommit 0e67c32commit 07353d9commit 3bc2702commit 8c3b9f7commit 80a539acommit c5c39f4(2019年3月13日)by SZEDER Gábor ( szeder ) .
参见commit 99e37c2commit 9f82b2acommit 900721e(2019年3月13日)by Johannes Schindelin ( dscho )
(由Junio C Hamano -- gitster --合并至commit 579b75a,2019年4月25日)

t9811-git-p4-label-import:固定流水线否定

在“t9811-git-p4-label-import.sh”中,测试“tag that cannot be exported”运行:

!(p4 labels | grep GIT_TAG_ON_A_BRANCH)

字符串
检查给定的字符串不是由' p4 labels '打印的。
这是有问题的,因为根据POSIX
“如果管道以保留字!开始,并且command1是子shell命令,则应用程序应确保command1开头的(运算符与!之间由一个或多个<blank>字符分隔开。

保留字!后面紧跟(运算符的行为未指定。

虽然大多数常见的shell仍然将此' ! '解释为“否定管道中最后一个命令的退出代码”,但' mksh/lksh '不这样做,而是将其解释为负文件名模式。
因此,它们试图运行由当前目录中的路径名组成的命令(它包含一个名为“main”的目录),当然,这会失败。
我们可以简单地通过在' ! '和' ( '之间添加一个空格来修复它,但是让我们通过删除不必要的子shell来修复它。特别是Commit 74ec8cf

相关问题