Раніше відповідь була представлена з тим, який зараз перший розділ, як останній розділ.
В оболонку POSIX Shell входить !
оператор
Роздумуючи над специфікацією оболонки для інших питань, нещодавно (вересень 2015 р.) Я помітив, що оболонка POSIX підтримує !
оператор. Наприклад, воно вказане як зарезервоване слово і може з’являтися на початку конвеєра - де проста команда є особливим випадком „конвеєра”. Отже, його можна використовувати в if
операторах та / while
або until
циклах - у оболонках, сумісних з POSIX. Отже, незважаючи на мої застереження, він, ймовірно, є більш доступним, ніж я уявляв у 2008 році. Швидка перевірка POSIX 2004 та SUS / POSIX 1997 показує, що він !
був присутній в обох версіях.
Зверніть увагу, що !
оператор повинен з'являтися на початку конвеєра і заперечує код стану всього конвеєра (тобто останньої команди). Ось кілька прикладів.
$ ! 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
Портативна відповідь - працює з антикварними черепашками
У сценарії Bourne (Korn, POSIX, Bash) я використовую:
if ...command and arguments...
then : it succeeded
else : it failed
fi
Це настільки портативно, наскільки це можливо. "Команда та аргументи" можуть бути конвеєром або іншою складеною послідовністю команд.
not
команда
"!" оператор, вбудований у вашу оболонку або наданий O / S, не є загальнодоступним. Написати це не страшно важко - наведений нижче код датується щонайменше 1991 р. (Хоча, я думаю, я писав попередню версію ще довше). Однак я не схильний використовувати це у своїх сценаріях, оскільки це недоступно.
/*
@(
@(
@(
@(
@(
@(
*/
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);
}
Це повертає "успіх", протилежний відмові, коли він не виконує команду. Ми можемо сперечатися, чи був правильним варіант „нічого не робити”; можливо, він повинен повідомити про помилку, коли його не просять щось робити. Код у ' "stderr.h"
' надає прості засоби звітування про помилки - я використовую його скрізь. Вихідний код на запит - див. Мою сторінку профілю, щоб зв’язатися зі мною.