Должен ли я заботиться о ненужных кошках?

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

сравнить

 sed s/bla/blaha/ data \ | grep blah \ | grep -n babla 

а также

 cat data \ | sed s/bla/blaha/ \ | grep blah \ | grep -n babla 

Является ли последний метод менее эффективным? Если да, то достаточно ли разницы, чтобы заботиться о том, запущен ли сценарий, скажем, один раз в секунду? Разница в читаемости не огромна.

4 Solutions collect form web for “Должен ли я заботиться о ненужных кошках?”

Конечно, «окончательный» ответ принес вам «Бесполезное использование cat награды» .

Цель cat – конкатенация (или «catenate») файлов. Если это только один файл, объединение его ни с чем не происходит, это пустая трата времени и стоит вам процесса.

Создание экземпляра кошки так, чтобы ваш код читал по-другому, делает только один процесс и еще один набор потоков ввода-вывода, которые не нужны. Как правило, реальное удержание в ваших сценариях будет неэффективным циклом и полной обработкой. В большинстве современных систем одна дополнительная cat не собирается убивать вашу производительность, но почти всегда есть другой способ написать свой код.

Большинство программ, как вы заметили, могут принимать аргумент для входного файла. Тем не менее, всегда существует оболочка builtin < которая может использоваться везде, где ожидается поток STDIN, который сохранит вам один процесс, выполнив работу в уже запущенном процессе оболочки.

Вы даже можете стать творческим, ГДЕ вы его пишете. Обычно он будет помещен в конце команды, прежде чем указывать любые перенаправления или каналы вывода следующим образом:

 sed s/blah/blaha/ < data | pipe 

Но этого не должно быть. Это может даже наступить первым. Например, ваш примерный код можно написать следующим образом:

 < data \ sed s/bla/blaha/ | grep blah | grep -n babla 

Если читаемость в сценариях является вашей проблемой, и ваш код достаточно грязный, что, как ожидается, добавление строки для cat упростит работу, есть и другие способы очистки вашего кода. Тот, который я использую много, что помогает сделать скрипты проще понять позже, разбивает трубы на логические множества и сохраняет их в функциях. Код сценария становится очень естественным, и любая часть конвейера легче отлаживать.

 function fix_blahs () { sed s/bla/blaha/ | grep blah | grep -n babla } fix_blahs < data 

Затем вы можете продолжить с помощью fix_blahs < data | fix_frogs | reorder | format_for_sql fix_blahs < data | fix_frogs | reorder | format_for_sql fix_blahs < data | fix_frogs | reorder | format_for_sql . Pipleline, который читает, как это, очень легко следовать, и отдельные компоненты могут быть легко отлажены в своих соответствующих функциях.

Ниже приведены некоторые из недостатков:

 cat $file | cmd 

над

 < $file cmd 
  • Во-первых, примечание: есть (намеренно для целей обсуждения) отсутствующие двойные кавычки вокруг $file выше. В случае cat это всегда проблема, кроме zsh ; в случае перенаправления это только проблема для bash или ksh88 а для некоторых других оболочек – только при интерактивном (не в скриптах).
  • Наиболее часто упоминаемый недостаток – это дополнительный процесс, порождаемый. Обратите внимание, что если cmd встроен, это даже 2 процесса в некоторых оболочках, таких как bash .
  • Все еще на фронте производительности, за исключением оболочек, в которых встроена cat выполняется также дополнительная команда (и, конечно, загружена и инициализирована (и библиотеки, к которым она также связана)).
  • Все еще на передней панели, для больших файлов, это означает, что системе придется поочередно планировать процессы cat и cmd и постоянно заполнять и очищать буфер буфера. Даже если cmd делает 1GB большой read() системных вызовов за один раз, управление должно идти туда и обратно между cat и cmd потому что в трубе не может храниться более нескольких килобайт данных за раз.
  • Некоторые cmd s (например, wc -c ) могут делать некоторые оптимизации, когда их stdin является обычным файлом, который они не могут сделать с cat | cmd cat | cmd поскольку их stdin – только труба. С cat и трубой это также означает, что они не могут seek() внутри файла. Для таких команд, как tac или tail , это имеет огромное значение в производительности, так как это означает, что с cat им нужно хранить весь ввод в памяти.
  • cat $file и даже более корректная версия cat -- "$file" не будут работать должным образом для некоторых определенных имен файлов, таких как - (или --help или что-то, начиная с - если вы забудете -- ). Если кто-то настаивает на использовании cat , он должен, вероятно, использовать cat < "$file" | cmd cat < "$file" | cmd вместо этого для надежности.
  • Если $file не может быть открыт для чтения (доступ запрещен, не существует …), < "$file" cmd будет сообщать о согласованном сообщении об ошибке (оболочкой) и не запускать cmd , а cat $file | cmd cat $file | cmd все равно будет работать cmd но с его stdin выглядит как пустой файл. Это также означает, что в таких случаях, как < file cmd > file2 , file2 не сбивается, если file не открывается.

Помещение <file в конец конвейера менее читаемо, чем наличие cat file в начале. Натуральный английский читается слева направо.

Полагаю, что <file a начало конвейера также менее читаемо, чем кошка, я бы сказал. Слово более читаемо, чем символ, особенно символ, который, кажется, указывает на неправильный путь.

Использование cat сохраняет command | command | command command | command | command формат command | command | command .

Одна вещь, на которую другие ответы здесь, по-видимому, прямо не затрагивает, заключается в том, что использование этого cat не является «бесполезным» в том смысле, что «посторонний процесс кошки порожден, который не работает»; это бесполезно в том смысле, что «происходит процесс кошки, который делает только ненужную работу».

В случае этих двух:

 sed 's/foo/bar/' somefile <somefile sed 's/foo/bar/' 

оболочка запускает sed-процесс, который считывает из somefile или stdin (соответственно), а затем выполняет некоторую обработку – он считывает до тех пор, пока он не ударит по новой строке, заменяет первый «foo» (если есть) в этой строке с «bar», а затем печатает это строка для stdout и циклов.

В случае:

 cat somefile | sed 's/foo/bar/' 

Оболочка порождает процесс кошки и процесс sed, и прокладывает stdout кота на stdin sed. Кошачий процесс читает несколько килобайт или, возможно, мегабайтный фрагмент из файла, а затем записывает его на его stdout, где sed sommand поднимается оттуда, как и во втором примере выше. В то время как sed обрабатывает этот кусок, кошка читает еще один кусок и записывает его в свой stdout для sed, чтобы работать дальше.

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

  • Проверьте, имеют ли файлы в определенном каталоге надлежащее расширение?
  • Копирование последних файлов с удаленных серверов
  • Простой, но правильный способ иметь сценарий bash отправлять вывод в журнал systemd?
  • Как использовать SSH для запуска сценария оболочки на удаленной машине?
  • Прочитайте два текстовых файла, объедините каждую строку
  • Проблемы при разметке eMMC с использованием sfdisk
  • Обнаруживать, если переменная пуста
  • Запустить RDP беззвучно?
  • Awk: печать последних N столбцов, где N передается через переменную
  • Непрерывный каталог резервных копий на USB-накопителе
  • почему Bash не будет добавлять мои переменные вместе?
  • Linux и Unix - лучшая ОС в мире.