Раздутая эхо-команда

Посмотрите на следующие реализации команды «echo»:

Просматривая список, я уверен, вы заметите увеличение раздувания в каждой реализации. В чем смысл эхо-программы 272 строки?


person Joe    schedule 20.07.2010    source источник


Ответы (3)


В своей статье «Разработка программы в среде UNIX» Пайк и Керниган обсуждают, как программа cat накапливала управляющие аргументы. Где-то, но не в этой статье, был комментарий о том, что "cat вернулся из Беркли, размахивая флагами". Это похоже на проблему с echo вариантами разработки. (Я нашел ссылку на соответствующую статью на справочной странице BSD (Mac OS X) для cat: Роб Пайк, Стиль UNIX или cat -v, считается вредным, USENIX Summer Conference Proceedings, 1983. См. также http://quotes.cat-v.org/programming/)

В своей книге «Среда программирования UNIX» Керниган и Пайк (да, снова эти двое) цитируют Дуга Макилроя по поводу того, что должно делать «эхо» без аргументов (около 1984 г.):

Другой вопрос философии заключается в том, что должна делать echo, если не заданы аргументы, в частности, должна ли она печатать пустую строку или вообще ничего. Все известные нам текущие реализации echo печатают пустую строку, но в прошлых версиях этого не было, и по этому поводу были большие дебаты. Дуг Макилрой придал правильное чувство мистицизма в своем обсуждении этой темы:

UNIX и эхо

Жила-была в земле Нью-Джерси Юникс, прекрасная дева, которой ученые путешествовали далеко, чтобы восхищаться ею. Ослепленные ее чистотой, все стремились жениться на ней, один из-за ее девственной грации, другой из-за ее изысканной вежливости, третий из-за ее ловкости в выполнении сложных задач, редко выполняемых даже в гораздо более богатых странах. Она была так великодушна и уступчива по своей природе, что UNIX принял всех, кроме самых невыносимо богатых из ее женихов. Вскоре многие потомки выросли и процветали и распространились по всему миру.

Сама природа улыбалась и отвечала UNIX более охотно, чем другим смертным существам. Скромные люди, которые мало знали о более придворных манерах, восхищались ее эхом, столь точным и кристально чистым, что они едва верили, что ей могут ответить те же скалы и леса, которые так искажали их собственные крики в пустыне. . И уступчивый UNIX отвечал безупречным эхом того, о чем бы ее ни спрашивали.

Когда один нетерпеливый мальчишка спросил UNIX: «Ничего не повторять», UNIX услужливо открыла рот, ничего не повторила и снова закрыла.

— Что ты имеешь в виду, — спросил юноша, — разинув рот вот так? Впредь никогда не открывай рта, если ты ничего не должен повторять! И UNIX обязан.

«Но я хочу идеального исполнения, даже если вы ничего не повторяете, — умолял чувствительный юноша, — и никакое идеальное эхо не может исходить из закрытого рта». Не желая обидеть ни того, ни другого, UNIX согласились ничего не говорить нетерпеливой молодежи и бесчувственной молодежи. Она назвала чувствительное ничто «\n».

Но теперь, когда она сказала «\n», она на самом деле ничего не сказала, поэтому ей пришлось открыть рот дважды, один раз, чтобы сказать «\n», и один раз, чтобы ничего не сказать, и поэтому она не понравилась чувствительному юноше, который тотчас же сказал: «\n звучит как идеальное ничто для меня, но второй все портит. Я хочу, чтобы ты забрал одну из них. Таким образом, UNIX, который не мог терпеть оскорбления, согласился отменить некоторые эхо-сигналы и назвал это «\c». Теперь чувствительный юноша мог услышать идеальное эхо ничего, попросив «\n» и «\c» вместе. Но говорят, что он умер от избытка нотной записи, даже не услышав ни одной.


Оболочка Korn представила (или, по крайней мере, включила) команду printf, которая была основана на функции printf() языка C и использует строку формата для управления тем, как должен выглядеть материал. Это лучший инструмент для сложного форматирования, чем echo. Но из-за истории, изложенной в цитате, echo больше не просто повторяется; он интерпретирует то, что ему дано эхом.

И интерпретация аргументов командной строки для echo несомненно требует больше кода, чем их не интерпретация. Основная эхо-команда:

#include <stdio.h>
int main(int argc, char **argv)
{
    const char *pad = "";
    while (*++argv)
    {
        fputs(pad, stdout);
        fputs(*argv, stdout);
        pad = " ";
    }
    fputc('\n', stdout);
    return 0;
}

Есть и другие способы добиться этого. Но более сложные версии echo должны тщательно проверять свои аргументы, прежде чем что-либо напечатать, а это требует больше кода. И разные системы решили, что они хотят по-разному интерпретировать свои аргументы, что приводит к разному количеству кода.

person Jonathan Leffler    schedule 20.07.2010

Вы заметите, что на самом деле не так много раздувания.

  1. Большинство строк кода являются комментариями.
  2. Большинство строк кода, которые не являются комментариями, представляют собой документацию по использованию, поэтому, когда кто-то вводит команду «echo --help», он что-то делает.
  3. Код за пределами приведенного выше, по-видимому, в основном обрабатывает аргументы, которые может принимать эхо, а также «специальное» расширение для таких символов, как \n и \t, чтобы они были их эквивалентными символами, а не повторяли их буквально.

Кроме того, большую часть времени вы даже не запускаете команду echo, большую часть времени «echo» вызывает встроенную оболочку. По крайней мере, на моей машине вам нужно набрать /bin/echo --help, чтобы получить всю расширенную функциональность/документацию, потому что echo --help просто эхо --help

В качестве хорошего примера запустите это в своей оболочке.

 echo '\e[31mhello\e[0m'

Затем запустите это:

 echo -e '\e[31mhello\e[0m'

И вы заметите совершенно разные результаты.

Первый просто выдаст ввод как есть, а второй напечатает hello красного цвета.

Другой пример с использованием шестнадцатеричного кода:

$echo '\x64\x65\x66'
\x64\x65\x66

$echo -e '\x64\x65\x66'
def

Совершенно разное поведение. Реализация openbsd не может этого сделать =).

person Kent Fredric    schedule 20.07.2010
comment
Я не знаю никакого C, но что-то явно выглядит немного помешанным. Например. строки 90~103 в эхе GNU, он преобразует некоторые шестнадцатеричные данные в целые числа. Но почему? OpenBSD может отображать текст, не возясь с шестнадцатеричными числами или чем-либо еще, кроме текста. Как я уже сказал, я не знаю никакого C; поэтому, пожалуйста, поправьте меня, если я ошибаюсь. - person Joe; 20.07.2010
comment
@Joe: openbsd просто копирует аргументы команды в стандартный вывод, а gnu действительно может обрабатывать данные. Смотрите мой пример. Затем попробуйте это на openbsd, используя абсолютный путь к «echo» вместо того, чтобы полагаться на встроенную оболочку. - person Kent Fredric; 20.07.2010
comment
Итак, GNU реализует несколько простых регулярных выражений менее чем в 300 строк, включая комментарии и лицензию. Я впечатлен! Спасибо. - person Joe; 20.07.2010
comment
@Kent Fredric: Тем не менее, это неплохо, учитывая размер. Я не могу поверить, что я никогда не знал! - person Joe; 20.07.2010
comment
echo --help должен отображать только '--help' и новую строку. Все остальное является неправильным толкованием того, для чего предназначено «эхо». - person Jonathan Leffler; 02.09.2010
comment
Версия GNU на самом деле делает почти то же самое (за исключением действительного расширения BSD -n) при запуске с определенной переменной среды POSIXLY_CORRECT и в обычной оболочке, которая уже обрабатывает экранированные символы. - person ; 06.09.2010
comment
И я бы не назвал версию FreeBSD раздутой. Очевидно, они стараются иметь самую быструю и маленькую версию в ущерб удобочитаемости. - person ; 06.09.2010

Я не уверен, нравится ли мне первая реализация: в ней слишком много вариантов!

Если требуется параметр -n, то также было бы полезно добавить параметр -- для остановки обработки параметров. Таким образом, если вы пишете сценарий оболочки, который считывает и печатает вводимые пользователем данные, вы не получите противоречивого поведения, если пользователь введет -n.

person Mikel    schedule 22.02.2011