Как я могу отрицать возвращаемое значение процесса? - программирование
Подтвердить что ты не робот

Как я могу отрицать возвращаемое значение процесса?

Я ищу простой, но кросс-платформенный процесс отрицания, который отрицает значение, возвращаемое процессом. Он должен отображать 0 на некоторое значение!= 0 и любое значение!= 0 на 0, то есть следующая команда должна возвращать "yes, nonexistingpath не существует":

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

The! - оператор велик, но, к сожалению, не является независимым от оболочки.

4b9b3361

Ответ 1

Ранее ответ был представлен тем, что теперь первый раздел как последний раздел.

POSIX Shell включает в себя ! оператор

Высказываясь вокруг спецификации оболочки для других проблем, я недавно (сентябрь 2015 года) заметил, что оболочка POSIX поддерживает ! оператор. Например, он указан как зарезервированное слово и может появляться в начале конвейера, где простая команда является частным случаем "конвейера". Поэтому его можно использовать в операторах if и while или until будут выполняться циклы - в POSIX-совместимых оболочках. Следовательно, несмотря на мои оговорки, он, вероятно, более широко доступен, чем я понял в 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 команда

"!" оператор, независимо от того, встроен ли он в вашу оболочку или предоставлен с помощью 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 death -- assume it failed */
    return (0);
}

Это возвращает "успех", противоположный сбою, когда он не выполняет команду. Мы можем обсуждать, правильно ли вариант "ничего не делать"; возможно, он должен сообщать об ошибке, когда ее не просят ничего сделать. Код в "stderr.h" "предоставляет простые средства отчетности об ошибках - я использую его везде. Исходный код по запросу - см. Мою страницу профиля, чтобы связаться со мной.

Ответ 2

В Bash используйте! оператора перед командой. Например:

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

Ответ 3

Вы можете попробовать:

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

или просто:

! ls nonexistingpath

Ответ 4

Если произойдет так, что у вас нет Bash в качестве оболочки (например, git скриптов или тестов кукольного exec), вы можете запустить:

echo '! ls notexisting' | bash

- > retcode: 0

echo '! ls /' | bash

- > retcode: 1

Ответ 5

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

или

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

Ответ 6

Примечание: иногда вы увидите !(command || other command).
Здесь ! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist." ! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist." достаточно.
Нет необходимости в под-оболочке.

Git 2.22 (Q2 2019) иллюстрирует эту лучшую форму с:

Фиксация 74ec8cf, фиксация 3fae7ad, фиксация 0e67c32, фиксация 07353d9, фиксация 3bc2702, фиксация 8c3b9f7, фиксация 80a539a, фиксация c5c39f4 (13 марта 2019 г.) от SZEDER Gábor (szeder).
См. Коммит 99e37c2, коммит 9f82b2a, коммит 900721e (13 марта 2019 г.) Йоханнеса dscho (dscho).
(Объединено Junio C Hamano - gitster - в коммите 579b75a, 25 апреля 2019 г.)

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 является командой subshell, приложение должно обеспечить, чтобы оператор ( в начале command1 отделился от ! Одним или несколькими <blank> символами.
Поведение зарезервированного слова ! сразу после ( оператор не указан. "

В то время как большинство обычных оболочек все еще интерпретируют это ! 'as' отменяет код выхода последней команды в конвейере ',' mksh/lksh 'не делает и интерпретирует его как отрицательный шаблон имени файла.
В результате они пытаются запустить команду, составленную из путей в текущем каталоге (он содержит один каталог с именем ' main '), что, конечно, не проходит тест.

Мы могли бы это исправить, просто добавив пробел между ' ! 'и' ( ', но вместо этого позвольте исправить это, удалив ненужную подоболочку. В частности, Commit 74ec8cf