Когда использовать Bash, а когда использовать Perl / Python / Ruby? [закрыто]

77

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

Как вы решаете, когда использовать Perl / Python / Ruby поверх Bash для скрипта? Я не думаю, что скрипт инициализации с Ruby имеет смысл, но как насчет немного более длинного скрипта, который добавляет учетные записи электронной почты?

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

Ответы:

44

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

Bash - это язык сценариев общего назначения, такой же, как Python, Ruby, Perl, но каждый из них имеет свои сильные стороны. Perl превосходен в анализе текста, Python претендует на звание самого элегантного из всех, сценарии Bash отлично справляются с "обкаткой", если вы понимаете, о чем я, и Ruby ... ну, Ruby немного особенный способов.

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

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

Также имейте в виду, что изучение сценариев оболочки очень просто. Реальная сила этого заключается в других программах, таких как awk, sed, tr и др.

mkaito
источник
У меня довольно большой опыт работы с bash-скриптингом, как с Ruby, но я иногда до сих пор не знаю, что использовать. Выбор, основанный на личных предпочтениях в данный момент времени, кажется глупым. Но вы правы, я спрошу себя, что я хочу сделать, и выберу лучший инструмент для работы.
futlib
Лично я буду использовать шкалу языков, которые я хорошо знаю, в порядке возрастания сложности и мощности, и буду использовать самый простой, который будет отвечать всем требованиям. Но на самом деле, единственный способ узнать наверняка - это написать сценарий на всех языках и сравнить результат. Это все больше внутреннее чувство, чем уверенность. После нескольких лет написания сценариев вы столкнетесь с большинством «типов проблем» и узнаете, на каком языке они успешно решаются.
mkaito
Просто хотел добавить, что используя небольшие программы из пакета GNU coreutils (такие как tr, sort, uniq) и передавая их по конвейеру, можно выполнять множество задач.
GMaster
57

TL; DR - используйте bash только для установки лучшего языка (если он еще не доступен), в противном случае вы теряете необратимое, драгоценное человеческое время. Если вы не можете сделать это вручную из командной строки без ошибок, не используйте скрипт bash / shell.

Это 2015 год, поэтому я хотел бы рассмотреть следующее:

  1. накладные расходы памяти

    • Затраты памяти на Ruby / Python во время выполнения по сравнению с bash незначительны (из-за разделяемых библиотек), хотя, вероятно, в любом случае невозможно поддерживать нетривиальный сценарий bash (т. Е. Сценарий с> 100 строками), поэтому использование памяти не является фактором
  2. время запуска

    • Запуск Ruby / Python может быть немного медленнее, но есть вероятность, что вы не собираетесь запускать много полных процессов Ruby / Python в узком цикле 100 раз в секунду (если у вас есть такие потребности, bash / shell слишком много накладных расходов в любом случае, и вам, вероятно, придется перейти на C / C ++)
  3. представление

    • в Ruby / Python почти все типичные обработки данных будут быстрее - или, по крайней мере, сопоставимы (или вам все равно нужен C / C ++ / Haskel / OCaml / что угодно)
    • реальная производительность / узкое место в исполнении (или даже производительность) почти никогда не будет "отсутствием использования bash / shell" (даже переключение черточки в Ubuntu для запуска показывает, как на самом деле проблема bash - и занятый ящик, вероятно, единственный вариант использования , потому что нет ничего больше , чем «Баш» и «VI» , чтобы писать и запускать код, и там часто нет возможности добавлять / загружать или хранить что - нибудь еще)
    • запуск других процессов для выполнения работы (например, sed / awk / grep) на самом деле на порядок медленнее, чем вызов метода для живого объекта в памяти
  4. производительность

    • слишком легко ошибаться в Bash / shell по сравнению с использованием «реальных» методов, параметров, переменных и исключений в Ruby / Python
    • Agile является основным направлением, в то время как Bash не поддерживает его (не хватает возможностей для модульного тестирования, библиотек, OO, модульности, линтинга, самоанализа, ведения журналов, метапрограммирования; практически невозможно провести рефакторинг без каких-либо нарушений)
    • слишком много несовместимостей с другими оболочками, второстепенные переменные окружения могут полностью сломать скрипт (и некоторые важные инструменты разработки, такие как Puppet, игнорируют строки shebang и передают или переписывают важные переменные оболочки), в то время как Ruby / Python имеют четко определенную относительно плавную миграцию пути даже для основных изменений версии
    • изучение нового языка занимает небольшую часть времени, затрачиваемого на отладку сценариев оболочки из-за специфических для оболочки проблем (в частности - имен переменных, без логических значений, исключений и т. д.)
    • даже сценарии запуска являются миной ( особенно потому, что они могут дать сбой во время запуска системы ), и, учитывая недавние недостатки безопасности с bash, вам может быть лучше использовать простой C (с хорошими библиотеками) - да, C требует компиляции, настройки и т. д. Но даже для простого сценария оболочки может потребоваться хранилище, затем управление версиями, а затем упаковка в любом случае.
    • все, что доступно с помощью sed / awk / grep, вероятно, уже встроено в Ruby / Python - без зависимости или «различий» между версиями этих инструментов на разных платформах (что если это работает в вашей настройке)
  5. безопасность работы
    • какой смысл искать работу, которая тебе не нравится? (если только вы не любите тратить все эти часы на сложные отладки, а на тривиальные ошибки в скриптах оболочки)

Я считаю, что нет смысла использовать Bash / Shell, если у вас установлен Ruby / Python.

И, вероятно, для установки Ruby / Python даже не нужен bash-скрипт (за исключением busybox, некоторые системные инструменты в любом случае зависят от наличия Python / Perl).

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

Почему люди сегодня используют Bash? Потому что это ужасная привычка, которую трудно сломать. Сценарий редко "завершается навсегда" после первых нескольких минут - независимо от того, насколько сильно люди склонны так думать. Вместе с ошибкой «это последняя ошибка в этом сценарии».

Вывод: используйте bash / shell только тогда, когда вы абсолютно вынуждены (например ~/.bashrc, busybox), потому что в настоящее время это почти никогда не «подходящий инструмент для работы».

Цезари Багинский
источник
28

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

Я использую Perl и python, когда основное внимание уделяю чтению данных из файлов, некоторой обработке этих данных и записи результатов в файлы. Если я обнаружу, что использую (в Perl) systemкоманду, тики назад или (в python) subprocessмодуль слишком широко, я считаю, что писать сценарий на bash. С другой стороны, я иногда начинаю добавлять столько функций в скрипт bash, что в конечном итоге имеет смысл переписать его на Perl / python, а не иметь дело с ограниченной (для сравнения) поддержкой bash для определения области переменных, функций, структур данных и т. Д. ,

chepner
источник
2
Я также использовал t0 в качестве залога для Bash всякий раз, когда требовалось чтение файла / генерация текста, но после изучения =~поддерживаемого оператора [[ ]]мне очень понравился Bash для простого чтения файла
Freedom_Ben
16

Мне нравятся критерии, изложенные в этом блоге .

  • Если нет аргументов для передачи, это, вероятно, сценарий оболочки.
  • Если для управляющей логики не так уж много (кроме одного цикла или if / else), это, вероятно, сценарий оболочки.
  • Если задача состоит в автоматизации инструкций командной строки, то это почти наверняка сценарий оболочки.
MarkTee
источник
8

Я нашел этот анализ Perl против Bash полезным ...

http://blogs.perl.org/users/buddy_burden/2012/04/perl-vs-shell-scripts.html

Для удобства я копирую краткое изложение этого автора: 1) когда bash - лучший вывод, и 2) когда perl - лучший вывод ...

Когда Bash лучше ...

  • Отказ от работы
  • Команды при выходе
  • Обработка строк вывода заданий
  • Здесь документы
  • Эквиваленты файлов
  • Сравнение временных меток файлов
  • Расширение тильды

Когда Perl лучше ...

Perl до сих пор не справляется с bash для большинства приложений. Причины, по которым я мог бы предпочесть Perl, включают (но не ограничиваются ими):

  • Это будет быстрее. Главным образом потому, что мне фактически не нужно запускать новые процессы для многих вещей, которые я хочу сделать (базовые имена и имена каталогов являются наиболее очевидными примерами, но обычно можно также исключить cut, grep, sort и wc).
  • Работа со строками в bash в лучшем случае рудиментарна, а вся система $ IFS супер-неуклюжа.
  • Условные выражения в сценариях оболочки могут быть сложными.
  • Цитирование в сценариях оболочки может быть кошмаром.
  • Заявление case в bash оставляет желать лучшего, кроме простых случаев (NPI).
  • Массивы в bash сосут. Хэши в bash (при условии, что ваш bash достаточно новый, чтобы их вообще иметь) сосут еще сильнее.
  • Как только обработка файлов или вывод команды выходит за рамки простого случая, который я перечислил выше, Perl начинает курить bash.
  • CPAN.

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

buzz3791
источник
Интересно, что в Ruby все (?) Из точек не применяются, потому что в Ruby есть at_exit (), realpath (), expand_path (), stat (), heredocs и exceptions ( fail "error" unless system("foobar")).
Цезари Багинский
5

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

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

Bash ближе к файловой системе и может отлично подойти для первого чернового варианта решения проблем, которые не определены четко. По этой причине bash-скрипт может быть хорошим первым вариантом для прототипирования чего-либо с полным намерением перенести его на python, как только проблема будет лучше понята.

Travis
источник
4

Bash - это оболочка Unix, включающая язык сценариев. Это скорее командный процессор. вы управляете тем, как вы запускаете команды, вы фактически запускаете их.

Perl / Ruby / Python являются языками общего назначения.

Когда вы хотите сценарий оболочки, вы используете Bash

Если вы хотите более сложную задачу или не связаны с оболочкой. Используйте Python и т. Д.

Я бы никогда не сравнил эти языки на самом деле. Python и т. Д. Являются портативными. Вы можете запустить их где угодно. Bash только для Unix.

Python и т. Д. Имеют тонны многократно используемых библиотек, решающих миллионы задач.

Это почти то же самое, если вы спросите. «Когда использовать Paint, а когда использовать Photoshop»

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

Но лучшим способом было бы совместить bash и ruby. Это было бы правильно. Как будто вы создаете сценарий обработки электронной почты в ruby, а bash-скрипт вызывает этот сценарий ruby ​​и запускает другие команды ds.

Поэтому, когда вам нужен командный процессор, вы используете bash. Вы запускаете команды Unix и управляете ими.

ОБНОВЛЕНИЕ через 7 лет (март 2019)

Хотя основная часть моего ответа не изменилась, я хотел бы отметить это.

Bash также является мощным скриптовым языком. Для обработки текста это может быть абсолютно законным выбором.

Пожалуйста, прочитайте комментарии mkaito ниже. Все они полностью правдивы.

bakytn
источник
1
Подмножество сценариев Bash так же общего назначения, как и любой язык сценариев общего назначения. Добавьте в программу общие программы, такие как sed, и вы получите 90% всех потребностей сценариев, которые у вас когда-либо будут.
mkaito
1
bash - это командный процессор, поэтому его мощь заключается в том, чтобы запускать другие команды и программы unix в их сценариях. Как вы упомянули sed и т. д. Он спрашивает, когда выбрать определенный язык
bakytn
1
Оболочка на самом деле является прославленным средством запуска программ, но ее возможности написания сценариев намного выше этого. Я предлагаю вам изучить некоторые настоящие сценарии оболочки.
mkaito
Я могу спать на полу, но я бы предпочел сделать это на кровати. Языки нельзя сравнивать, они имеют разные цели.
Баку
2
Хорошо, если Bash - слово, что-то вроде Haskell должно быть гвоздем :-)
mkaito
1

Сценарии оболочки, такие как bash, ksh, zsh, sh и fish, как известно, удивительны по сравнению с универсальными языками высокого уровня, такими как Ruby, Python или Perl. Хотя сценарий оболочки может начать свою жизнь в виде более короткого файла, чем эквивалентный сценарий общего назначения, неожиданности приводят к большому количеству защитного кода, например, set -euo pipefailдля включения строгих режимов.

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

mcandre
источник
1

Очень предвзятая статья.

Я не считаю, что bash так сложно отлаживать. Python часто слишком жесток, тогда как bash позволяет вам быть очень креативным. Если вы хороший нестандартный мыслитель, вам понравится Bash.

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

Я думаю, что bash, как и perl, не самый удобный и легкий для чтения. Это пугает людей, потому что большинство людей не являются великими абстрактными мыслителями. Но более яркие, более творческие программисты любят это и часто используют его. Если ты знаешь себя и знаешь, что у тебя есть мозг, не пугайся bash. Если вы простой мыслитель, возможно, придерживайтесь чего-то вроде Python. Каждому свое.

CK
источник
0

Из "Книги ламы"

  • Рэндал Л. Шварц, Том Феникс и Брайан дой Фой, Learning Perl (Севастополь, Калифорния: O'Reilly, 2011), гл. 1.2 "Что означает Perl?" , §§ «Почему Ларри [создатель Perl] просто не использовал какой-то другой язык?», С. 5:

Perl пытается заполнить пробел между низкоуровневым программированием (например, в C или C ++ или сборке) и высокоуровневым программированием (таким как «командное» программирование [например, bash]). Низкоуровневое программирование, как правило, трудно писать и безобразно, но быстро и без ограничений; Трудно превзойти скорость хорошо написанной низкоуровневой программы на данном компьютере. И там не так много, что вы не можете сделать там. Высокоуровневое программирование, с другой стороны, имеет тенденцию быть медленным, сложным, безобразным и ограниченным; есть много вещей, которые вы вообще не можете сделать с помощью командного или командного программирования, если в вашей системе нет команды, обеспечивающей необходимую функциональность. Perl легок, почти безграничен, в основном быстр и немного уродлив.

Geremia
источник
0

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

А что касается читабельности, Bash ужасен, если ваш стиль программирования ужасен. Если вы просто выбросите туда код, он станет неясным.

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

Как образец, это мой последний код на Bash. Обратите внимание, как легко понять и напечатать это:

#! /bin/bash


mainFunction () {
    file="${1}"

    checkFile "${file}"
    executeFile "${file}"
}


changeToThisProgramDir () {
    cd "$( dirname "${BASH_SOURCE[0]}" )"
}


checkFile () {
    file="${1}"

    checkFileNotEmpty "${file}"
    checkFileExist "${file}"
    checkFileIsExe "${file}"
}


checkFileExist () {
    file="${1}"

    if [ ! -f "${file}" ]; then
        echo "The file doesn't exist: ${file}" >&2
        echo "If the name was correct either type: exeCute \"pathToYourExeFile\""
        echo "Or just open with exeCute from the file manager"
        exit 1
    fi
}


checkFileIsExe () {
    file="${1}"
    mime=$(fileMime "${file}")

    if [ "${mime}" != "application/x-dosexec" ]; then
        echo "Not an exe: ${file}" >&2
        exit 1
    fi
}


checkFileNotEmpty () {
    file="${1}"

    if [ "${file}" == "" ]; then
        echo "No file specified" >&2
        echo "Either type this: exeCute \"pathToYourExeFile\""
        echo "Or just open with exeCute from the file manager"
        exit 1
    fi
}


execute () {
    function="${1}"
    command="${2}"
    error=$(eval "${command}" 2>&1 >"/dev/null")

    if [ ${?} -ne 0 ]; then
        echo "${function}: ${error}" >&2
        exit 1
    fi
}


executeFile () {
    file="${1}"
    type=$(fileType "${file}")

    if [ "${type}" == "MS-DOS executable" ]; then
        execute "executeFile" "dosbox \"${file}\" -forcescaler normal2x -exit -fullscreen"
    else
        execute "executeFile" "wine \"${file}\""
    fi
}


fileMime () {
    file="${1}"

    attributes=$(file --brief --mime "${file}")
    IFS=";" read -r -a attributes <<< "${attributes}"
    echo "${attributes[0]}"
}


fileType () {
    file="${1}"

    attributes=$(file --brief "${file}")
    IFS="," read -r -a attributes <<< "${attributes}"
    echo "${attributes[0]}"
}


changeToThisProgramDir
mainFunction "${@}"
Альберто Сальвия Новелла
источник