Обработка '-' в аргументах /bin/sh: POSIX vs реализациями с помощью Bash/Dash/FreeBSD sh

Я хочу вызвать /bin/sh и использовать параметр -c для передачи команды "+ x" , то есть для выполнения программы с именем "+ x" , имя которой начинается со знака "плюс".

Так как "+ x" интерпретируется как /bin/sh как опция (в частности, отключить опцию "x" ),/bin/sh следует запретить интерпретировать его как параметр. Я получаю следующие различные результаты в зависимости от используемого /bin/sh:

(1) Первый вариант:

/bin/sh -c -- +x

Использование Dash и Bash в Linux: выполняется команда + x.

Использование FreeBSD sh: выполняется команда - и устанавливается опция + x.

(2) Второй вариант:

/bin/sh -c +x

Использование Dash и Bash в Linux: параметр + x установлен, и есть ошибка, потому что в опции -c отсутствует аргумент.

Использование FreeBSD sh: выполняется команда + x.

(3) Третий вариант:

/bin/sh -c - +x

Использование Dash и Bash в Linux: + x выполняется.

Использование FreeBSD sh: выполняется команда - и устанавливается опция + x.

(4) Четвертый вариант: (ADDED, как указано в комментариях)

/bin/sh -c+x

Использование Dash и Bash в Linux: Неверный/Нелегальный вариант "+"

Использование опции FreeBSD sh: Bad -c


Мой вопрос: что задает POSIX?

Я читаю спецификацию POSIX для sh здесь: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sh.html

Цитата из этого: "Один дефис рассматривается как первый операнд, а затем игнорируется. Если оба параметра" - "и" - "указаны в качестве аргументов или если другие операнды предшествуют одному дефису, результаты undefined".

Я не уверен, относится ли эта цитата к одной тире, помещенной сразу после '-c'.

Итак, какой из них прав, Dash/ Bash или FreeBSD? Или, если оба правильные, потому что POSIX позволяет обоим, как сделать это переносимо?

Ответ 1

Ответ на вопрос "Что назначает Posix" уже присутствует в OP. Но важная особенность стандарта Posix не выделяется: параметр -c не принимает аргумент.

Вы можете увидеть это в Сводке:

sh -c [-abCefhimnuvx] [-o option]... [+abCefhimnuvx] [+o option]...
      command_string [command_name [argument...]]

То, что делает флаг -c, является причиной того, что позиционные параметры ( "операнды" ) интерпретируются по-другому. Без -c они интерпретируются как [command_file [argument...]]:

sh [-abCefhimnuvx] [-o option]... [+abCefhimnuvx] [+o option]...
   [command_file [argument...]]

Это, кстати, почему sh -c+x является ошибкой. Если -c принял аргумент, тогда было бы законным включать аргумент в одно и то же слово.

Итак, чтобы ответить на более конкретные вопросы:

  • Posix говорит: "Один дефис рассматривается как первый операнд, а затем игнорируется...". Это относится к - сразу после -c?

    A: Да, это так. -c - это полная опция, поэтому - является операндом. Напротив, - в -o - не будет рассматриваться как операнд. (Это будет рассматриваться как недопустимое имя опции.)

  • Какой из них прав, Dash/ Bash или FreeBSD?

    A: В этом случае Dash и Bash являются Posix-совместимыми, а FreeBSD sh - нет. Оболочка FreeBSD значительно предшествует текущей спецификации Posix, и я не верю, что она когда-либо утверждала, что она полностью соответствует любой спецификации Posix.

  • Как можно с помощью sh использовать команду sh для запуска команды, имя которой начинается с +?

    A: Я бы подумал, что в любой оболочке будет работать следующее:

    sh -c " +x"
    

    " +x" не будет распознаваться как опция, поскольку он не начинается с + или -, а sh -c заставляет операнд разбираться как команду оболочки, поэтому ведущие пробелы будут игнорироваться, У меня нет копии FreeBSD ash, чтобы играть с этого момента, поэтому я приветствую исправления.

    Или вы можете использовать простую составную команду:

    sh -c "{ +x; }"
    

    Возможно, самый ясный (при условии, что используемая оболочка реализует встроенный в Posix встроенный command):

    sh -c "command +x"