Я не знал о награде до сегодняшнего дня, когда какой-то новичок попытался наколоть UUOC на меня для одного из моих ответов. Это было cat file.txt | grep foo | cut ... | cut ...
. Я дал ему часть своего разума, и только после этого посетил ссылку, которую он дал мне, ссылаясь на происхождение награды и практику этого. Дальнейшие поиски привели меня к этому вопросу. К сожалению, несмотря на сознательное рассмотрение, ни один из ответов не содержал моего обоснования.
Я не хотел защищаться, обучая его. В конце концов, в мои молодые годы я написал бы команду так, grep foo file.txt | cut ... | cut ...
потому что всякий раз, когда вы выполняете частые одиночные grep
операции, вы изучаете расположение аргумента файла, и вы уже знаете, что первым является шаблон, а последующими - имена файлов.
Это был осознанный выбор, когда я ответил на вопрос с cat
префиксом частично из-за причины «хорошего вкуса» (по словам Линуса Торвальдса), но главным образом из-за неотразимой причины работы.
Последняя причина более важна, поэтому я изложу ее в первую очередь. Когда я предлагаю трубопровод в качестве решения, я ожидаю, что его можно будет использовать повторно. Вполне вероятно, что конвейер будет добавлен в конце или объединен в другой конвейер. В этом случае файл , имеющий аргумент Grep щурит многократное использование, и вполне возможно , сделать это тихо и без сообщения об ошибке , если файл существует аргумент. И. е. grep foo xyz | grep bar xyz | wc
даст вам , сколько строк в xyz
содержат в bar
то время как вы ожидаете , количество строк , которые содержат как foo
и bar
. Необходимость изменить аргументы команды в конвейере перед ее использованием подвержена ошибкам. Добавьте к этому возможность молчаливых неудач, и это станет особенно коварной практикой.
Не менее важна и первая причина, так как много «хорошего вкуса» просто является интуитивным подсознательным обоснованием таких вещей, как молчаливые неудачи, описанные выше, о которых вы не можете вспомнить в тот момент, когда кто-то, нуждающийся в образовании, говорит «но это не так». этот кот бесполезен ".
Тем не менее, я постараюсь также осознать прежнюю причину «хорошего вкуса», которую я упомянул. Эта причина связана с духом ортогонального дизайна Unix. grep
не делает cut
и ls
не делает grep
. Поэтому, по крайней мере, grep foo file1 file2 file3
идет вразрез с духом дизайна. Ортогональный способ сделать это cat file1 file2 file3 | grep foo
. Теперь, grep foo file1
это просто особый случай grep foo file1 file2 file3
, и если вы не относитесь к нему одинаково, вы, по крайней мере, используете мозговые циклы, пытаясь избежать бесполезного награждения кошек.
Это приводит нас к аргументу, который grep foo file1 file2 file3
объединяет и cat
объединяет, так что это уместно, cat file1 file2 file3
но потому, что cat
мы не объединяемся, cat file1 | grep foo
поэтому мы нарушаем дух как cat
всемогущего, так и всемогущего Unix. Что ж, если бы это было так, тогда Unix потребовалась бы другая команда, чтобы прочитать вывод одного файла и выложить его на стандартный вывод (не разбивать его на страницы или что-то еще, просто наплевать на стандартный вывод). Таким образом, у вас возникнет ситуация, когда вы говорите cat file1 file2
или говорите dog file1
и добросовестно помните, чтобы избежать того, cat file1
чтобы избежать получения награды, и при этом избегать, dog file1 file2
так как, надеюсь, дизайн dog
выдаст ошибку, если будет указано несколько файлов.
Надеемся, что в этот момент вы сочувствуете разработчикам Unix за то, что вы не включили отдельную команду для разбрызгивания файла на стандартный вывод, а также назвали cat
конкатенацию вместо того, чтобы давать ей другое имя. <edit>
есть такая собака, несчастный <
оператор. К сожалению, его размещение в конце трубопровода препятствует легкому составлению. Не существует синтаксически или эстетически чистого способа разместить его в начале. К сожалению, недостаточно универсален, поэтому вы начинаете с собаки, а просто добавляете другое имя файла, если хотите, чтобы оно обрабатывалось после предыдущего. (С >
другой стороны, он не в два раза хуже. У него почти идеальное расположение в конце. Обычно он не является частью многоразового использования конвейера, и, соответственно, он символически выделяется.)</edit>
Следующий вопрос: почему важно иметь команды, которые просто плюют файл или объединяют несколько файлов в стандартный вывод без какой-либо дальнейшей обработки? Одна из причин - избегать использования каждой отдельной команды Unix, работающей со стандартным вводом, чтобы знать, как анализировать хотя бы один аргумент файла командной строки и использовать его в качестве ввода, если он существует. Вторая причина заключается в том, чтобы пользователям не приходилось запоминать: (а) куда идут аргументы имени файла; и (b) избежать ошибки тихого конвейера, как упомянуто выше.
Это подводит нас к тому, почему grep
есть дополнительная логика. Логическое обоснование состоит в том, чтобы обеспечить свободное владение пользователями для команд, которые используются часто и автономно (а не как конвейер). Это небольшой компромисс ортогональности для значительного увеличения удобства использования. Не все команды должны быть разработаны таким образом, и команды, которые не часто используются, должны полностью избегать дополнительной логики аргументов файла (помните, что дополнительная логика приводит к ненужной хрупкости (возможность ошибки)). Исключением является разрешение файловых аргументов, как в случае grep
. (кстати, обратите внимание, что у ls
него совершенно другая причина не просто принимать, а в значительной степени требовать аргументы файла)
Наконец, то, что можно было бы сделать лучше, - это если такие исключительные команды, как grep
(но не обязательно ls
), генерируют ошибку, если доступен стандартный ввод. Это разумно, потому что команды включают логику, которая нарушает ортогональный дух всемогущего Unix для удобства пользователя. Для дальнейшего удобства пользователя, т.е. для предотвращения страданий, вызванных молчаливым отказом, такие команды не должны стесняться нарушать собственное нарушение, предупреждая пользователя, если существует возможность молчаливого отказа.