Когда и как двойная тире (-) была введена как конец разделителя опций в Unix / Linux?

49

Я не думаю, что оболочка / утилиты в историческом Unix или в чем-то «недавнем», как 4.4BSD, поддерживали использование двойного тире (или двух последовательных дефисов) в качестве конца разделителя опций . В FreeBSD вы можете увидеть, например, заметку, представленную на rm страницах руководства с выпуском 2.2.1 (1997). Но это только документация для одной команды.

Глядя на самый старый журнал изменений файловой утилиты GNU, который я могу найти, я вижу это 1 (слегка измененное):

Tue Aug 28 18:05:24 1990  David J. MacKenzie  (djm at albert.ai.mit.edu)

* touch.c (main): Don't interpret first non-option arg as a   <---
  time if `--' is given (POSIX-required kludge).  
* touch.c: Add long-named options.
* Many files: Include <getopt.h> instead of "getopt.h" since
  getopt.h will be in the GNU /usr/include.
* install.c: Declare some functions.
* touch.c, getdate.y, posixtime.y, mktime.c: New files, from bin-src.
* posixtime.y: Move year from before time to after it (but
  before the seconds), for 1003.2 draft 10.

Это предшествует Linux . Очевидно, что необходимо учитывать тот факт, что вам может потребоваться создать файл с именем, содержащим то же количество цифр, что и в спецификации времени (десятичное или восьмизначное число), а не указывать временную метку для существующего файла ...


  • Так это же posix.1, который ввел double-dash ( --) в качестве конца разделителя опций в оболочках Unix?
  • Началось ли все это потому, что некоторые люди хотели использовать цифры в именах файлов touchв начале 90-х, а затем это происходило по частям по одной утилите за десятилетие?
  • О чем этот оживленный комментарий в журнале изменений?
  • Когда Рекомендация 10 ( аргумент - должен быть принят в качестве разделителя, указывающего конец параметров. [...] ) введена в синтаксис служебной программы POSIX ?

1. В отличие от этого, т. Е. Документирование длинных опций во всех командах, используемых глобально, что не имеет никакого отношения. С другой стороны, вы можете увидеть ссылки на ограничителе появляются в чем - то вроде GNU rm.c в 2000 году в качестве комментария, перед тем , как подвергается конечному пользователю в 2005 году ( diagnose_leading_hyphen функции). Но это все гораздо позже и касается очень конкретного случая использования.

Жиль "ТАК - перестань быть злым"
источник
1
BSD4.3RENO, по крайней мере getopt, поддерживает --.
Стефан Шазелас
@ StéphaneChazelas Вы также сделали комментарий о том, что getopt не является единственным API, способным иметь дело с разделителем. Означает ли это, что это было предусмотрено и работало до того, как оно фактически использовалось? Боюсь, это за мной. Спасибо!
2
Вероятно, он использовался на разовой основе несколькими случайными программами, но я думаю, что он впервые стал документированным, когда getoptбыл написан в начале 1980-х годов. Если кто-то может получить документ getopt от Uniforum '85, это может дать некоторую историю.
Марк Плотник
2
@MarkPlotnick, на самом деле поддерживается getopt, найденный в SysIII (1980) --.
Стефан Шазелас

Ответы:

38

Насколько я могу судить, использование в --качестве маркера конца опций начинается shи getoptв System III Unix (1980).

Согласно этой истории семейства Bourne Shell , Bourne Shell впервые появилась в Версии 7 Unix (1979). Но это не есть способ для setчтобы отделить параметры от аргументов . Итак, оригинальная оболочка Bourne могла бы сделать:

  • set -e - включить режим выхода при ошибке
  • set arg1 arg2 ...- устанавливает позиционные параметры $1=arg1, $2=arg2и т.д.

Но: set arg1 -e arg2даст вам $1=arg1, $2=arg2и включить выход-на-ошибки . Упс.

Система III Unix (1980) исправила эту ошибку и представила getopt. Согласно getoptсправочной странице :

NAME
   getopt - parse command options

SYNOPSIS
   set -- `getopt optstring $∗`

DESCRIPTION
   Getopt is used to break up options in command lines for easy parsing by
   shell procedures, and to check  for  legal  options.   Optstring  is  a
   string  of  recognized  option letters (see getopt(3C)); if a letter is
   followed by a colon, the option is expected to have an  argument  which
   may or may not be separated from it by white space.  The special option
   -- is used to delimit the end of the options.  Getopt will place --  in
   the  arguments  at  the  end  of  the  options, or recognize it if used
   explicitly.  The shell arguments ($1 $2 . . .) are reset so  that  each
   option  is  preceded  by a - and in its own shell argument; each option
   argument is also in its own shell argument.

Насколько я могу судить, это первое место, которое появляется.

Оттуда, кажется, что другие команды приняли --соглашение, чтобы разрешить неоднозначности разбора аргументов (такие как примеры с touchи rmвы цитируете выше) в течение диких, нестандартных дней 1980-х.

Некоторые из этих частичных усыновлений были кодифицированы в POSIX.1 (1988), отсюда и комментарий в журнале изменений о "POSIX-обязательном клудже".

Но только в POSIX.2 (1992) были приняты Рекомендации по синтаксису служебных программ , которые содержат знаменитое Руководство 10:

Guideline 10:    The argument "--" should be accepted as a delimiter
                 indicating the end of options.  Any following
                 arguments should be treated as operands, even if they
                 begin with the '-' character.  The "--" argument
                 should not be used as an option or as an operand.

И вот откуда он превращается из «клуджа» в универсальную рекомендацию.

wwoods
источник
Спасибо, что нашли время! Я в основном игнорировал getopt в своих «исследованиях», так как не понимаю, зачем нужна такая абстрактная утилита / функция. Теперь я прочитал, что в какой-то момент это было переработано (getopts), чтобы справиться с пробелами и т. Д., Как sysv getoptне смог. Я буду читать больше об этом! Еще раз спасибо!
5
Если вы не понимаете, почему была бы полезна стандартная утилита для анализа параметров командной строки, возможно, вы не пробовали написать анализатор оболочки для параметров командной строки? Это какая-то боль! Конечно, было бы неплохо, если бы какой-нибудь другой инструмент сделал это для меня ... Кроме того, имейте в виду: в 1980 году не было ни Python, ни Ruby, ни Java, ни Perl, ни PHP - даже C ++ еще не был изобретен, и Вся идея «сценариев оболочки» была все еще довольно новой. Так что идея стандартного парсера командной строки все еще была довольно новой!
Вудс