Соответствует ли POSIX использование функции оболочки в конвейере?

Можно ли использовать функцию оболочки в конвейере?

Скажем, у меня была функция, которая действовала как grep, называется mygrep, Есть ли способ, используя только функции оболочки POSIX, чтобы иметь возможность вызыватьmygrep как это:

if ps | mygrep foo ; then
   echo "process foo is running"
fi

Или трубопровод ограничен только внешними командами?

2 ответа

Решение

Да. Смотрите этот документ .

1. Введение

В разделе "Shell and Utilities" в POSIX.1-2017 описываются команды и утилиты, предлагаемые прикладным программам в POSIX-совместимых системах.

От 2.9.2 Трубопроводы :

Конвейер представляет собой последовательность из одной или нескольких команд, разделенных оператором управления '|'.

С 2.9.5 Команда определения функции :

Функция - это пользовательское имя, которое используется в качестве простой команды [...]

Формат команды определения функции следующий:

fname ( ) compound-command [io-redirect ...]

Из 2.9 Команды оболочки :

Команда является одной из следующих:

  • Простая команда [...]
  • [...]

Так | разделяет команды; команда может быть простой командой; Имя функции используется как простая команда. Ответ на ваш вопрос: да, этот синтаксис

some_command | some_function

определяется POSIX.


Это довольно легко попробовать (протестировано с sh предоставлено dash в Debian 9):

mygrep() { grep "$@"; }

if ps | mygrep foo ; then
   echo "process foo is running"
fi

if ps | mygrep ps ; then
   echo "process ps is running"
fi

( ps | mygrep foo обнаружит процесс foobar а также, если таковые имеются. Я понимаю, что этот вопрос выходит за рамки вашего вопроса, и мы можем его игнорировать).

В этом примере mygrep тривиально Возвращает статус выхода своей последней (и единственной) команды. При построении функций с более сложной логикой вам может потребоваться специальная встроенная return вернуть желаемый статус выхода.

Также обратите внимание на вывод из grep не подавляется. В каналах можно использовать не только функцию оболочки, но и ее вывод. Пример:

if ps | mygrep ps >/dev/null ; then
   echo "process ps is running"
fi

Вы должны использовать форму oneliner или упаковать выражение в ${}. В той форме, которую вы написали как bash-скрипт, это невозможно.

Другие вопросы по тегам