однострочник против скрипта

25

Я заметил много вопросов, ответов и комментариев, выражающих презрение к (а иногда и боязнь) написания сценариев вместо однострочников. Итак, я хотел бы знать:

  • Когда и почему я должен писать отдельный скрипт, а не «однострочник»? Или наоборот?

  • Каковы варианты использования и плюсы и минусы обоих?

  • Некоторые языки (например, awk или perl) лучше подходят для однострочников, чем другие (например, python)? Если так, то почему?

  • Это просто вопрос личных предпочтений или есть веские (то есть объективные) причины для написания того или другого в конкретных обстоятельствах? Каковы эти причины?

Определения

  • one-liner: любая последовательность команд, введенная или вставленная непосредственно в командную строку оболочки . Часто с участием трубопроводов и / или использование языков , таких как sed, awk, perl, и / или инструменты , такие как grepили cutили sort.

    Определяющим признаком является прямое выполнение в командной строке - длина и форматирование не имеют значения. «Однострочный» может быть все в одной строке, или он может иметь несколько строк (например, sh for loop, или встроенный код awk или sed, с переводом строки и отступом для улучшения читабельности).

  • script: любая последовательность команд на любом интерпретируемом языке (ах), которые сохраняются в файл и затем выполняются. Сценарий может быть написан полностью на одном языке, или это может быть оболочка сценария оболочки вокруг нескольких «однострочников», использующих другие языки.


У меня есть собственный ответ (который я опубликую позже), но я хочу, чтобы это стало каноническим вопросом и ответами на эту тему, а не только моим личным мнением.

саз
источник
4
Что касается Python, это обычно плохо для однострочников, потому что пробел является частью синтаксиса, включая отступы и переводы строки . Кроме того, это более многословно и явно, чем большинство других распространенных языков.
wjandrea
2
Все, что мне приходилось гуглить (обычно с некоторым регулярным выражением) и может использовать повторно в той или иной форме или варианте, я сохраню в файле сценария в облаке (dropbox, облако Google, что угодно). Комментарий содержит ключевые слова, которые я собираюсь использовать, когда они понадобятся мне снова. Это экономит 5 + минут, пересматривая мой выбор между различными подобными ответами, избегая ловушек или создавая необходимый вариант, так как я не нашел точного хорошо написанного варианта, который мне нужен.
user3445853
3
@wjandrea Добавить: регулярные выражения. Perl имеет специальный синтаксис для них, который включает в себя выполняемую операцию и т. Д. В python вам нужны вызовы функций import и write с строковыми литералами в качестве аргументов, которые принимают намного больше символов. Большинство однострочников используют множество регулярных выражений для манипулирования текстом, так что это «большая проблема».
Джакомо Альзетта
1
@wjandrea Python неплох для однострочников, не в том смысле, что не может их написать. В среднем я смог преобразовать 4-5-строчные сценарии в однострочные. Но, как вы упомянули, он более явный, чем другие языки (имхо, это одно из преимуществ Python). Таким образом, они могут получить двойное или тройное количество символов, чем, скажем, Perl или awk (которые также не нуждаются в импорте некоторых библиотек, в отличие от Python), и именно на это жалуется большинство людей - длина этих однострочников. Но опять же, ИМХО, мелочно спорить о количестве персонажей; если что-то работает - работает
Сергей Колодяжный

Ответы:

33

Еще один ответ, основанный на практическом опыте.

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

for h in host1 host2 host3; do printf "%s\t%s\n" "$h" "$(ssh "$h" uptime)"; done

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

#!/bin/bash
# Check the uptime for each of the known set of hosts
########################################################################
#
hosts=(host1 host2 host3)

for h in "${hosts[@]}"
do
    printf "%s\t" "$h"
    uptime=$(ssh -o ConnectTimeout=5 -n "$h" uptime 2>/dev/null)
    printf "%s\n" "${uptime:-(unreachable)}"
done

Обобщая, можно сказать

  • Один лайнер

    • Простой код (т. Е. Просто «несколько» операторов), написанный для конкретной одноразовой цели
    • Код, который можно написать быстро и легко, когда это необходимо
    • Одноразовый код
  • скрипт

    • Код, который (вероятно) будет использоваться более одного или двух раз
    • Сложный код, требующий более «нескольких» операторов
    • Код, который нужно будет поддерживать другим
    • Кодекс, понятный другим
    • Код для запуска без присмотра (например, с cron)

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

roaima
источник
Это хороший практический пример того, как быстрый и грязный однострочник может превратиться в более надежный сценарий.
Энтони Дж. - правосудие для Моники
Это хорошее начало, но есть еще одна возможность. У меня есть некоторые вещи, которые удобно использовать более одного или двух раз, но, вероятно, не на одной машине. Я сохраняю их в текстовом файле, который я постоянно открываю на своем рабочем компьютере, чтобы я мог быстро скопировать их и вставить в мой SSH-клиент (или, если уж на то пошло, командную строку на сервере Windows). Это не обязательно «один лайнер», и я не стараюсь сохранять их в файлах как «скрипты». Я называю их "рецептами".
Монти Хардер
@MontyHarder В таких случаях я склонен сохранять их как скрипты, а затем сохранять их в git-репо. Затем я могу просто установить их на любую нужную мне машину с помощью простого клона git. Это для работы. Для личного использования я никогда не пишу код в файле "рецепта" (например, я не использую фрагменты github). Я сохраняю все свои скрипты в каталоге $ HOME / bin, который я хранил с 1997 года (в университетах SunOS). Я получил идею из романа «Нейромант», где и главный герой, и антагонист хранили личные сценарии / программы для использования в качестве оружия
slebetman
1
Хотя это, конечно , касательная к реальной дискуссии, в вашем примере сценария вы можете использовать set -- host1 host2 host3то for h in "$@"(или просто for h), что сделало бы сценарий POSIX переносимым. :-)
wchargin
2
Мне нравится мысль о том, чтобы сделать код более читабельным для OP и зрителей. Лучше всего сделать и то и другое в ответе, но я считаю, что проще связать сценарий с разбором одного элемента лично.
FreeSoftwareServers
10

Напишите скрипт, когда:

  • требуется больше кода
  • вы цените удобочитаемость
  • необходимо / полезно добавлять комментарии, чтобы показать, что делает код
  • вам нужно передать параметры
  • вы хотите, чтобы скрипт выполнялся в собственной среде (переменные и т. д.)
  • вы, вероятно, собираетесь повторно использовать / адаптировать код для более сложной цели

Написать однострочник, когда:

  • требуется только небольшое количество кода
  • вы хотите получить доступ к переменным, определенным в текущей оболочке
  • вам нужно быстрое и грязное решение
dr01
источник
Обычно легко изменить то, что работает на одной строке. Эта точка «передачи параметров» для скрипта может быть «вы хотите упаковать ее для простого использования позже». Я написал «однострочники», которые включают определение функции оболочки и ее вызов. Хотя теперь, когда я думаю об этом, он успокоился после нескольких итераций, и я должен поместить его в сценарий.
Питер Кордес
9

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

По сути, я думаю, что однострочники - это то, что опытный системный администратор, знакомый как с проблемой, так и с используемыми командами, может написать на месте, не слишком задумываясь.

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

В Python отступ является частью синтаксиса, поэтому вы буквально не можете использовать возможности языка в полной мере, если пишете в одну строку.

Perl и awk one-liners часто используют грубую мощь регулярных выражений. Но некоторые называют регулярные выражения языком только для записи, не совсем без причины. Написание многострочного сценария позволяет вам писать в комментариях описание того, что должно делать определенное регулярное выражение, что будет очень полезно, когда вы снова посмотрите на сценарий, выполнив другие действия в течение шести месяцев между ними.

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

Лучшее часто является врагом достаточно хорошего , и это очень применимо здесь.

И если вы знакомы с Perl, вы, возможно, уже слышали о TMTOWTDI: существует не только один способ сделать это.

Телком
источник
плюс один за упоминание "или функции оболочки"
Гленн Джекман
7

Обратите внимание, что это личное мнение; возьмите это с зерном соли.

  1. Если команда вмещает, скажем, 80 символов, используйте одну строку. С длинными командными строками сложно работать. Там также проблема повторения, см. № 2

  2. Если вам нужно выполнить команду (и) более одного раза, используйте скрипт. В противном случае используйте однострочник, если выполняется условие № 1.

  3. Это очень субъективно, но да, я вижу shell, Perl или awk как инструмент для перехода на одну строку.
  4. Смотрите № 1, № 2, № 3.
schaiba
источник
3
Мне нравятся ответы, которые я видел до сих пор. Мне особенно нравится ваш первый пункт - редактирование - это одна из вещей, которую я планировал упомянуть в своем ответе - даже с ^ X ^ E гораздо проще и гораздо приятнее редактировать скрипт в вашем любимом редакторе, чем редактировать по команде. линия.
Cas
2
Хотя голосование по пункту 4 кажется бессмысленным. :)
Энтони Дж - правосудие для Моники
@cas: с помощью клавиши со стрелкой управления (или alt + f / alt + b) вы можете перемещаться в одной строке очень быстро. Особенно, если у вас есть ключевые настройки автоповтора, например, 50 / сек с кратковременной задержкой, например, 220 мс. Вы также можете использовать команду control-s / control-r в пределах одной строки, хотя это может вернуть вас в другую историю. Если вы хорошо справляетесь с control-w, alt + backspace, alt + d и control-y, вы можете многое сделать, просто перемещая курсор мыши.
Питер Кордес
Кроме того, в некоторых оболочках IIRC (например, ZSH, я думаю) есть привязка клавиш для вызова редактора в текущей командной строке, что позволяет вам составлять «одну строку» в вашем любимом редакторе и легко вводить ее в историю команд для дальнейшего повышения. стрелка и редактирование. (Возможность изменить его для повторного запуска - это то, что делает однострочники отличными по сравнению с обработкой параметров командной строки в скрипте.) IIRC, bash также имеет внешнее редактирование, но по умолчанию не привязано ни к чему.
Питер Кордес
@PeterCordes очень быстрое перемещение курсора даже не начинает сравниваться с тем, что вы можете сделать в приличном редакторе, таком как vi / vim. Кстати, ^ X ^ E вызывает $ EDITOR или $ VISUAL в bash (и некоторых других оболочках. Zsh тоже, я думаю. настраивается). это хороший способ превратить нечитаемый беспорядок, который я создал, во что-то понятное, вставляя переводы строк и отступы - легко потеряться во вложенных скобках или скобках без них. Кстати, мои терминальные окна имеют ширину более 250 символов, поэтому мои строки могут быть очень длинными даже без переноса.
саз
7

Я рассматриваю и использую однострочник в качестве временного инструмента разработки для многократного редактирования, пока он не сделает то, что я хочу, или я не понимаю, как работает некоторая тонкость подкоманды.

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

Я установил, что моя история оболочки составляет более 5000 строк, с отдельной историей для каждого терминала и для каждого входа в систему на удаленном компьютере и так далее. Ненавижу, что не могу найти в этих историях команду, состоящую из одной строки, которую я разработал несколько недель назад и не думал, что она мне понадобится снова, отсюда и моя стратегия.

Иногда целая группа команд должна что-то делать, например, настраивать какое-то оборудование; в конце я копирую их все из истории, минимально очищаю их и добавляю в сценарий оболочки, RUNMEкак заметки о том, что я сделал, но так, чтобы они были почти готовы для повторного использования кем-то другим. (Вот почему я нахожу инструменты, которые предоставляют только графический интерфейс для настройки их такой боли.) Я считаю, что это невероятный выигрыш в эффективности, так как часто то, что вы ожидаете сделать только один раз, должно быть сделано еще 5 раз ... ,

meuh
источник
1
+1 однострочники отлично подходят для стрелок вверх и редактирования, в отличие от реализации параметров командной строки для скрипта, чтобы контролировать, что он делает отдельно от того, над чем он работает. например, изменение по lnсравнению ln -sс жесткими и мягкими ссылками в однострочнике, которое перебирает некоторые файлы.
Питер Кордес
5

Я хотел бы, чтобы люди в моей команде писали сценарии для любых операций, которые могут потребоваться выполнять более одного раза (т. Е. «Рабочие процессы» или «конвейеры»), и для любой одноразовой задачи, которую требуется документировать (обычно такие вещи, как «изменить некоторые вещи в некотором наборе данных, чтобы исправить неправильно предоставленные данные» в нашем случае). Кроме того, «однострочники» или сценарии не имеют большого значения.

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

Это независимо от того, какой язык используется для программирования.

Другие рабочие места могут иметь сходные / другие обычаи или ожидания, может быть, даже записаны.

Дома вы делаете все, что хотите.

Например, я пишу сценарии, как только делаю что -то нетривиальное в оболочке, например, перед отправкой ответа на вопрос U & L, или всякий раз, когда мне нужно проверить отдельные компоненты команды или набора команд перед выполнением этого «для реальный».

Я также пишу сценарии для повторяющихся задач, которые я действительно хочу делать одинаково каждый раз, даже если они просты, как

  • обновить мою систему OpenBSD и все установленные пакеты (это сводится к трем коротким командам и нескольким другим для ведения домашнего хозяйства, собранным в короткий скрипт), или
  • резервное копирование моей системы в стороннее хранилище (по сути, одной командой, но опять же с довольно большим количеством служебных операций, и сценарий также позволяет мне делать различия между снимками и т. д., и он должен работать слегка по-разному в разных системах, и Я запускаю его с помощью cron) или
  • извлечение почты (опять же, по сути, одна команда, но я хочу, чтобы она работала по-разному, когда вызывается как задание cron и когда я использую ее из командной строки, и при некоторых обстоятельствах она не должна пытаться извлекать почту, и она пишет короткое сообщение журнала в файл).

Я использую функции оболочки (очень редко называемые псевдонимами) для удобства в интерактивных оболочках, например, для добавления опций к определенным командам по умолчанию ( -Fдля ls) или для создания специализированных вариантов некоторых команд ( pmanздесь, например, manкоманда, которая просматривает только руководства по POSIX) ,

Кусалананда
источник
5

Похоже, я придерживаюсь мнения меньшинства по этому вопросу.

Термин «сценарий» намеренно сбивает с толку, избавьтесь от него. Это программное обеспечение, которое вы пишете там, даже если вы используете исключительно bashи awk.

В команде я предпочитаю писать программное обеспечение с процессом проверки кода, навязанным инструментом (github / gitlab / gerrit). Это дает контроль версий в качестве бонуса. Если у вас несколько систем, добавьте инструменты непрерывного развертывания. И некоторые тестовые наборы, если целевые системы важны. Я не религиозен по этому поводу, но взвешиваю выгоды и издержки.

Если у вас есть команда администраторов, самое простое vim /root/bin/x.sh- это, в основном, катастрофа с точки зрения связи, связанной с изменениями, читаемости кода и межсистемного распространения. Часто одна серьезная неисправность стоит больше времени / денег, чем предположительно «тяжелый» процесс.

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

Важное различие между (не прошедшими обзор!) Однострочниками и проверенным программным обеспечением («сценариями»): ответственность за вас полностью ложится на вас при выполнении однострочников. Вы никогда не можете сказать себе : «Я только что нашел это один-лайнер где - то, я побежал , не понимая, что за этим последовало не моя вина» - вы знали , что вы работаете Нерецензированное и непроверенное программное обеспечение бит из-, так что это ваша вина. Убедитесь, что он достаточно мал, чтобы вы могли предвидеть результаты - будьте прокляты, если вы этого не сделаете.

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

kubanczyk
источник
1
Хорошая мысль: мне больше нравится термин «программа», а не «сценарий».
Гленн Джекман
5

Должен сказать, что я несколько испуган последствиями первых частей вопроса. Языки сценариев Unix - это полноценные языки программирования, а языки программирования - это языки , а это означает, что они почти так же бесконечно гибки и гибки, как и человеческие языки. И одна из отличительных черт «бесконечной гибкости и гибкости» заключается в том, что почти никогда не существует «одного правильного способа» выражения чего-либо - существуют разные способы, и это хорошо! Так что, да, конечно , это вопрос личных предпочтений, и в этом нет ничего плохого. Любой, кто говорит, что есть только один способ сделать что-то,

Однажды мой ~/binбыл полон «полезных» маленьких сценариев, которые я написал. Но я понял, что большинство из них привыкли к тому дню, когда я их написал, и больше никогда. Таким образом, чем больше времени проходит, тем меньше binстановится мой каталог.

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

Причины, по которым я больше не пишу сценарии (и, я думаю, предпочитаю «однострочники»):

  • binбеспорядок в каталогах имеет свою стоимость. Я больше не кладу туда вещи, если они действительно не принадлежат там.
  • Языки сценариев, которые я использую, являются языками, которые я использую ; Я действительно легок с ними. Перепечатывание однострочника всякий раз, когда мне нужно, не похоже на работу; Я не чувствую себя обязанным хранить, сохранять и использовать скрипт только для того, чтобы облегчить (пере) набирать текст. (Среди прочего, в какой-то момент нагрузка на перепечатывание становится меньше, чем нагрузка на память, возникающая при запоминании сценария.)
  • Еще одна причина, по которой перепечатывание вещей не кажется бременем, это история команд. Есть много строк, которые я не включил в сценарии, хотя я использую их каждый день - но мне не нужно их перепечатывать; Я просто вспоминаю их из истории. Таким образом, это своего рода сценарии или псевдонимы бедняков.
Стив Саммит
источник
4

Я полагаю, что большую часть времени запрос на «однострочник» на самом деле является запросом на «укус», то есть:

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

Люди хотят и просят самый короткий код, который демонстрирует решение поставленного вопроса.

Иногда нет возможности свести речь к «звуковому фрагменту», а также невозможно сделать сценарий коротким «однострочным». В таких случаях единственным возможным ответом является сценарий.

И, в общем, «укус звука» никогда не является хорошей заменой всей речи. Таким образом, «один вкладыш», как правило, хорош только для того, чтобы передать идею или привести практический пример этой идеи. Затем, после того, как идея понята, она должна быть расширена (применена) в сценарии.

Итак, напишите «однострочник», чтобы передать идею или концепцию.

Напишите свой общий код в виде полных сценариев, а не однострочников.

Исаак
источник
1

Вы спрашиваете о «страхе и презрении сценариев». Это связано с ситуацией Q + A, где ответ часто звучит так: нужен этот шаг и этот, но я также могу поместить его в одну строку (чтобы вы могли скопировать, вставить его и использовать в качестве длинной простой команды).

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

Многие плюсы и минусы здесь верны, но все же они упускают суть. Я бы даже сказал, что определения в Q не помогают.

Файлы истории оболочки являются «однострочниками», но все же они сохраняются. Функция bash operate-and-get-next (C-o)даже позволяет вам повторять их полуавтоматически.

Я едва вижу упомянутое слово « функция» . Это способ хранения как «скриптов», так и «однострочников». И с помощью нескольких нажатий клавиш вы можете переключаться между обоими форматами. Команда соединение часто может соответствовать обоим.

history -r fileэто способ чтения одной или нескольких командных строк (и комментариев) из любого файла, а не только из файла истории по умолчанию. Это просто требует минимальной организации. Вы не должны полагаться на большой размер файла истории и поиск в истории, чтобы получить (некоторую) версию командной строки.

Функции должны быть определены аналогичным образом. Для начала поместите thisfunc() {...}файл "functions" в домашнюю директорию и поставьте его. Да, это некоторые накладные расходы, но это общее решение.

Если вы храните каждую командную строку и каждый вариант сценария в отдельном файле, это (теоретическая, но объективная) пустая трата блоков файловой системы.

У одной строки нет ничего быстрого и грязного само по себе. Это скорее часть копирования-вставки, которая немного осуждается, и то, как мы просто полагаемся на историю команд, чтобы сохранить ее для нас.


@sitaram: ваш один лайнер действительно имеет ип-onelinerish возможности: строка shebang, символ новой строки, четыре вызова утилит - два из них - «программы». Я думаю, что оригинальный скрипт на Perl выглядел лучше и работал быстрее и не тратил впустую ни одного байта, распределяясь на 60 строк И Perl также позволяет вам немного сжать.

Для меня это именно тот тип лайнера, которого следует избегать. Хотели бы вы, чтобы это было (вставлено) в вашей командной строке? Нет, и затем, если вы все равно сохраните его в файле (независимо от сценария или функции), вы можете потратить два или три байта новой строки, чтобы он выглядел - приятно.


10 минут. позже: я просто хотел проверить, могу ли я сказать «две программы sed» или «две замены / вызовы sed». Но ответа Ситарама больше нет. Мой ответ все еще имеет смысл, я надеюсь.

rastafile
источник