Wcześniej odpowiedź była przedstawiana jako ostatnia sekcja, która jest teraz pierwszą sekcją.
POSIX Shell zawiera !
operator
Przeglądając specyfikację powłoki pod kątem innych problemów, niedawno (wrzesień 2015) zauważyłem, że powłoka POSIX obsługuje !
operatora. Na przykład jest wymieniony jako słowo zastrzeżone i może pojawić się na początku potoku - gdzie proste polecenie jest specjalnym przypadkiem „potok”. Dlatego może być używany w if
instrukcjach i / while
lub until
pętlach - w powłokach zgodnych z POSIX. W konsekwencji, pomimo moich zastrzeżeń, jest prawdopodobnie szerzej dostępny, niż zdawałem sobie sprawę w 2008 roku. Szybkie sprawdzenie POSIX 2004 i SUS / POSIX 1997 pokazuje, że !
był obecny w obu tych wersjach.
Zauważ, że !
operator musi pojawić się na początku potoku i zanegować kod statusu całego potoku (tj. Ostatnie polecenie). Oto kilka przykładów.
$ ! some-command succeed; echo $?
1
$ ! some-command fail | some-other-command fail; echo $?
0
$ ! some-command < succeed.txt; echo $?
1
$ ! RESULT=fail some-command; echo $?
0
$ 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
Przenośna odpowiedź - działa z antycznymi muszlami
W skrypcie Bourne'a (Korn, POSIX, Bash) używam:
if ...command and arguments...
then : it succeeded
else : it failed
fi
To jest tak przenośne, jak to tylko możliwe. „Polecenie i argumenty” może być potokiem lub inną złożoną sekwencją poleceń.
not
komenda
Znak '!' Operator, niezależnie od tego, czy jest wbudowany w twoją powłokę, czy dostarczany przez O / S, nie jest powszechnie dostępny. Nie jest jednak strasznie trudno napisać - poniższy kod pochodzi przynajmniej z 1991 roku (choć myślę, że poprzednią wersję napisałem nawet wcześniej). Nie używam tego jednak w moich skryptach, ponieważ nie jest to niezawodnie dostępne.
/*
@(
@(
@(
@(
@(
@(
*/
static const char sccs[] = "@(#)$Id: not.c,v 4.2 2005/06/22 19:44:07 jleffler Exp $";
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);
}
Zwraca „sukces”, przeciwieństwo niepowodzenia, gdy nie wykonuje polecenia. Możemy debatować, czy opcja „nic nie rób z powodzeniem” była słuszna; może powinien zgłosić błąd, gdy nie jest proszony o nic. Kod w „ "stderr.h"
” zapewnia proste narzędzia do raportowania błędów - używam go wszędzie. Kod źródłowy na życzenie - zobacz moją stronę profilu, aby się ze mną skontaktować.