code

프로세스의 반환 값을 어떻게 부정 할 수 있습니까?

codestyles 2020. 10. 5. 07:57
반응형

프로세스의 반환 값을 어떻게 부정 할 수 있습니까?


프로세스가 반환하는 값을 부정 하는 단순하지만 크로스 플랫폼 부정 프로세스를 찾고 있습니다. 0을 일부 값! = 0으로 매핑하고 모든 값! = 0을 0으로 매핑해야합니다. 즉, 다음 명령은 "예, 존재하지 않는 경로가 존재하지 않습니다"를 반환해야합니다.

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

! -연산자는 훌륭하지만 안타깝게도 셸 독립적이지 않습니다.


이전에는 마지막 섹션으로 현재 첫 번째 섹션이 무엇인지 대답이 제시되었습니다.

POSIX Shell에는 !연산자가 포함되어 있습니다.

다른 문제에 대한 셸 사양을 살펴보면서 최근 (2015 년 9 월) POSIX 셸이 !연산자를 지원한다는 것을 알았습니다 . 예를 들어 예약어 로 나열되고 파이프 라인 의 시작 부분에 나타날 수 있습니다. 여기서 간단한 명령은 'pipeline'의 특별한 경우입니다. 따라서 POSIX 호환 셸 에서 if문 및 while/ 또는 until루프에서도 사용할 수 있습니다 . 결과적으로 내 예약에도 불구하고 2008 년에 깨달은 것보다 더 널리 사용 가능할 것입니다. POSIX 2004와 SUS / POSIX 1997을 빠르게 확인하면 !두 버전 모두에 존재 하는 것으로 나타났습니다 .

점을 유의 !운영자가에 나타나야 시작 파이프 라인의 전체 파이프 라인의 상태 코드 (즉, 부정 마지막 명령). 여기 몇 가지 예가 있어요.

# 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

휴대용 대답-골동품 조개와 함께 작동

Bourne (Korn, POSIX, Bash) 스크립트에서 다음을 사용합니다.

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

이것은 가져 오는 것만 큼 휴대 가능합니다. '명령 및 인수'는 파이프 라인 또는 기타 복합 명령 시퀀스 일 수 있습니다.

not명령

'!' 연산자는 쉘에 내장되어 있든 운영 체제에서 제공하든 보편적으로 사용할 수 없습니다. 하지만 작성하기가 끔찍하게 어렵지는 않습니다. 아래 코드는 적어도 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);
}

This returns 'success', the opposite of failure, when it fails to execute the command. We can debate whether the 'do nothing successfully' option was correct; maybe it should report an error when it isn't asked to do anything. The code in '"stderr.h"' provides simple error reporting facilities - I use it everywhere. Source code on request - see my profile page to contact me.


In Bash, use the ! operator before the command. For instance:

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

You could try:

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

or just:

! ls nonexistingpath

If somehow happens that you don't have Bash as your shell (for ex.: git scripts, or puppet exec tests) you can run:

echo '! ls notexisting' | bash

-> retcode: 0

echo '! ls /' | bash

-> retcode: 1


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

or

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

Note: sometimes you will see !(command || other command).
Here ! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist." is enough.
No need for a sub-shell.

Git 2.22 (Q2 2019) illustrates that better form with:

Commit 74ec8cf, commit 3fae7ad, commit 0e67c32, commit 07353d9, commit 3bc2702, commit 8c3b9f7, commit 80a539a, commit c5c39f4 (13 Mar 2019) by SZEDER Gábor (szeder).
See commit 99e37c2, commit 9f82b2a, commit 900721e (13 Mar 2019) by Johannes Schindelin (dscho).
(Merged by Junio C Hamano -- gitster -- in commit 579b75a, 25 Apr 2019)

t9811-git-p4-label-import: fix pipeline negation

In 't9811-git-p4-label-import.sh', the test 'tag that cannot be exported' runs:

!(p4 labels | grep GIT_TAG_ON_A_BRANCH)

to check that the given string is not printed by 'p4 labels'.
This is problematic, because according to POSIX:

"If the pipeline begins with the reserved word ! and command1 is a subshell command, the application shall ensure that the ( operator at the beginning of command1 is separated from the ! by one or more <blank> characters.
The behavior of the reserved word ! immediately followed by the ( operator is unspecified."

While most common shells still interpret this '!' as "negate the exit code of the last command in the pipeline", 'mksh/lksh' don't and interpret it as a negative file name pattern instead.
As a result, they attempt to run a command made up of the pathnames in the current directory (it contains a single directory called 'main'), which, of course, fails the test.

We could fix it simply by adding a space between the '!' and '(', but instead let's fix it by removing the unnecessary subshell. In particular, Commit 74ec8cf

참고URL : https://stackoverflow.com/questions/367069/how-can-i-negate-the-return-value-of-a-process

반응형