Kiedy używać Bash, a kiedy Perl / Python / Ruby? [Zamknięte]

78

Do tej pory robiliśmy wszystkie skrypty z Bash, ale zaczynam czuć się trochę głupio z tego powodu. Chociaż możemy oczywiście robić wszystko, co chcemy z Bash (jest dość potężny), zaczynam się zastanawiać, czy zamiast tego nie powinniśmy używać odpowiedniego języka skryptowego (w naszym przypadku najprawdopodobniej Ruby).

Jak decydujesz, kiedy używać skryptu w Perlu / Pythonie / Ruby w Bash? Nie sądzę, aby skrypt inicjujący z Ruby miał sens, ale co powiesz na nieco dłuższy skrypt, który dodaje konta e-mail?

futlib
źródło
1
Jeśli możesz to zrobić za pomocą jednego z nich, czy to naprawdę ma znaczenie? Wybór jest interesujący tylko wtedy, gdy powstały skrypt wykazuje jakiekolwiek różnice. Na przykład czas wykonania może się znacznie różnić (nie jest to problem w przypadku kont e-mail).
Dennis

Odpowiedzi:

44

Biorąc pod uwagę problem, z którym obaj mogą sobie poradzić, będziesz chciał użyć tego, z którym czujesz się najlepiej. Ostatecznie istnieje wiele drobnych szczegółów, a tylko doświadczenie może ich nauczyć.

Bash jest językiem skryptowym ogólnego przeznaczenia, takim jak Python, Ruby, Perl, ale każdy z nich ma inne mocne strony niż reszta. Perl przoduje w analizie tekstu, Python twierdzi, że jest najbardziej elegancki ze wszystkich, skrypty Bash doskonale nadają się do „przesuwania rzeczy”, jeśli wiesz, co mam na myśli, a Ruby ... cóż, Ruby jest trochę wyjątkowa sposobów.

Jednak różnice między nimi naprawdę mają znaczenie tylko wtedy, gdy masz wystarczająco dużo doświadczenia w pisaniu skryptów. Sugeruję wybranie jednego języka i przesunięcie go do granic możliwości przed przejściem do następnego. Możesz zrobić wiele w skrypcie powłoki, więcej niż większość ludzi przyzna. Każdy język jest tak trudny, jak chcesz. Po napisaniu kilku rzeczy, każdy język jest dla ciebie „łatwy”.

Znajomość powłoki szybko się opłaca, jeśli mieszkasz w Linuksie, więc może chcesz zacząć od tego. Jeśli znajdziesz zadanie, którego wykonanie w skrypcie powłoki jest niemożliwe lub niepraktyczne, użyj czegoś innego.

Pamiętaj też, że nauka skryptów powłoki jest bardzo prosta. Prawdziwa moc tego leży w innych programach, takich jak awk, sed, tr i in.

mkaito
źródło
Mam spore doświadczenie ze skryptami bash, podobnie jak z Ruby, ale czasami wciąż nie wiem, czego użyć. Wybieranie na podstawie osobistych preferencji w tym momencie wydaje się głupie. Ale masz rację, zadam sobie pytanie, co chcę zrobić i wybiorę najlepsze narzędzie do pracy.
futlib
Osobiście użyję skali języków, które znam dobrze, w rosnącej kolejności złożoności i mocy, i użyję najprostszych, które pasują do rachunku. Ale tak naprawdę jedynym sposobem, aby się upewnić, jest napisanie skryptu we wszystkich językach i porównanie wyników. To bardziej przeczucie niż pewność. Po kilku latach pisania skryptów natkniesz się na większość „rodzajów problemów” i będziesz wiedział, który język dobrze je rozwiązał.
mkaito
Chciałem tylko dodać, że za pomocą małych programów w pakiecie GNU coreutils (takich jak tr, sort, uniq) i ich potokowanie można wykonać wiele zadań.
GMaster,
58

TL; DR - używaj bash tylko do instalowania lepszego języka (jeśli nie jest już dostępny), w przeciwnym razie marnujesz nieoceniony, cenny ludzki czas. Jeśli nie możesz tego zrobić ręcznie w wierszu poleceń bez błędów, nie pisz w bash / shell.

Jest 2015, więc rozważę następujące kwestie:

  1. narzut pamięci

    • Narzut pamięci w środowisku wykonawczym Ruby / Python w porównaniu do bash jest niewielki (z powodu bibliotek współdzielonych), podczas gdy prawdopodobnie i tak nie jest w stanie utrzymać nietrywialnego skryptu bash (tj. Z> 100 liniami) - więc użycie pamięci nie jest czynnikiem
  2. czas uruchomienia

    • Uruchamianie Ruby / Python może być nieco wolniejsze, ale są szanse, że nie będziesz uruchamiał wielu pełnych procesów Ruby / Python w ciasnej pętli 100 razy na sekundę (jeśli masz takie potrzeby, bash / shell jest i tak za dużo narzutu i prawdopodobnie będziesz musiał przejść do C / C ++)
  3. występ

    • prawie wszystkie typowe crunchowanie danych będzie szybsze w Ruby / Python - lub przynajmniej porównywalne (lub w każdym razie potrzebujesz C / C ++ / Haskel / OCaml / cokolwiek)
    • prawdziwą wydajnością / wąskim gardłem w wykonywaniu (a nawet produktywności) prawie nigdy nie będzie „brak korzystania z bash / shell” (nawet dosk przełączania Ubuntu do uruchamiania pokazuje, w jaki sposób problem stanowi bash - a busybox jest prawdopodobnie jedynym przypadkiem użycia , ponieważ nie ma nic więcej niż „bash” i „vi” do pisania i uruchamiania kodu, a często nie ma możliwości dodania / pobrania lub zapisania czegokolwiek innego)
    • uruchamianie innych procesów w celu wykonania zadania (takich jak sed / awk / grep) jest w rzeczywistości wolniejsze niż wywołanie metody na obiekcie na żywo w pamięci
  4. wydajność

    • zbyt łatwo jest popełniać błędy w Bash / shell w porównaniu do używania „rzeczywistych” metod, parametrów, zmiennych i wyjątków w Ruby / Python
    • Agile jest głównym nurtem, podczas gdy Bash nie ma na to wsparcia (brak możliwości testowania jednostkowego, bibliotek, OO, modułowości, linkowania, introspekcji, logowania, metaprogramowania; prawie niemożliwe jest refaktoryzacja bez zepsucia czegoś)
    • zdecydowanie za dużo niezgodności z innymi powłokami, drobne zmienne środowiskowe mogą całkowicie zepsuć skrypt (a niektóre ważne narzędzia programistyczne, takie jak Puppet, ignorują linie shebang i przekazują lub przepisują ważne zmienne powłoki), podczas gdy Ruby / Python mają dobrze zdefiniowaną stosunkowo płynną migrację ścieżki nawet dla głównych zmian wersji
    • nauka nowego języka zajmuje ułamek czasu alternatywnie spędzanego na debugowaniu skryptów powłoki ze względu na problemy specyficzne dla powłoki (w szczególności - nazwy zmiennych, brak wartości logicznych, żadnych wyjątków itp.)
    • nawet skrypty startowe są miną ( zwłaszcza dlatego, że mogą zawieść podczas uruchamiania systemu ), a biorąc pod uwagę ostatnie błędy bezpieczeństwa związane z bash, lepiej będzie użyć zwykłego C (z dobrymi bibliotekami) - tak, C wymaga kompilacji, konfiguracji itp. , ale nawet prosty skrypt powłoki może wymagać repozytorium, a następnie wersjonowania, a następnie pakowania.
    • cokolwiek jest dostępne z sed / awk / grep, prawdopodobnie jest już wbudowane w Ruby / Python - bez zależności lub „różnic” między wersjami tych narzędzi na różnych platformach (co z tego, jeśli działa w twojej konfiguracji)
  5. bezpieczeństwo pracy
    • jaki jest sens zabezpieczenia pracy, której nie lubisz? (chyba że lubisz spędzać te wszystkie godziny na trudnych do debugowania, ale trywialnych do wykonania błędach skryptów powłoki)

Uważam, że nie ma powodu, aby używać Bash / Shell, jeśli masz zainstalowany Ruby / Python.

I prawdopodobnie zainstalowanie Ruby / Pythona nawet nie potrzebuje skryptu bash w pierwszej kolejności (z wyjątkiem busyboksa, niektóre narzędzia systemowe zależą od obecności Pythona / Perla).

I za każdym razem, gdy piszesz skrypt powłoki, „ćwiczysz”, robiąc dokładnie to - zamiast uczyć się czegoś mocniejszego / wydajniejszego.

Dlaczego ludzie korzystają obecnie z Bash? Ponieważ jest to okropny, trudny do złamania nawyk. Skrypt rzadko jest „kończony na zawsze” po pierwszych kilku minutach - bez względu na to, jak silnie ludzie myślą w ten sposób. Wraz z błędem „to ostatni błąd w tym skrypcie”.

Wniosek: używaj bash / shell tylko wtedy, gdy jesteś absolutnie do tego zmuszony (np. ~/.bashrcBusybox), ponieważ w dzisiejszych czasach prawie nigdy nie jest to „odpowiednie narzędzie do pracy”.

Cezary Bagiński
źródło
28

Korzystam z bash, gdy główny nacisk kładę na obsługę plików. Może to obejmować przenoszenie, kopiowanie i zmianę nazw plików, a także wykorzystywanie plików jako danych wejściowych dla innych programów lub przechowywanie wyników innych programów w plikach. Rzadko piszę kod bash, który faktycznie sprawdza zawartość pliku lub generuje dane wyjściowe do zapisu do pliku; Pozostawiam to innym programom (które mogę pisać w Perlu lub Pythonie), które uruchamiam przez bash.

Używam Perla i Pythona, kiedy moim głównym celem jest odczytywanie danych z plików, przetwarzanie tych danych w jakiś sposób i zapisywanie danych wyjściowych w plikach. Jeśli okaże się, systemże subprocesszbyt często używam (w Perlu) polecenia, zaznacza wstecz lub (w pythonie) moduł, rozważam napisanie skryptu w bash. Z drugiej strony czasami zaczynam dodawać tak wiele funkcji do skryptu bash, że ostatecznie sensowniej jest przepisać go w Perl / python, zamiast zajmować się ograniczoną (przez porównanie) obsługą bash dla zakresu zmiennych, funkcji, struktur danych itp. .

chepner
źródło
2
Użyłem t0 również za kaucją na Bash za każdym razem, gdy wymagane było czytanie pliku / generowanie tekstu, ale po zapoznaniu się z =~operatorem wspieranym przeze [[ ]]mnie
pokochałem
16

Lubię kryteria określone w tym poście na blogu .

  • Jeśli nie ma żadnych argumentów do przekazania, prawdopodobnie jest to skrypt powłoki.
  • Jeśli nie ma wiele dla logiki sterowania (oprócz pojedynczej pętli lub jeśli / else), to prawdopodobnie jest to skrypt powłoki.
  • Jeśli zadaniem jest automatyzacja instrukcji wiersza poleceń, prawie na pewno jest to skrypt powłoki.
MarkTee
źródło
8

Uważam, że ta analiza Perla kontra Basha jest przydatna ...

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

Dla wygody kopiuję streszczenie tego autora 1) kiedy bash jest lepszym odkryciem i 2) kiedy perl jest lepszym wnioskiem ...

Kiedy Bash jest lepszy ...

  • Brak pracy
  • Polecenia przy wyjściu
  • Przetwarzanie linii wyników pracy
  • Tutaj Dokumenty
  • Plik Równoważności
  • Porównania sygnatury czasowej pliku
  • Rozszerzenie Tilde

Kiedy Perl jest lepszy ...

Perl wciąż bije bzdury w większości aplikacji. Powody, dla których wolę Perla, to (między innymi):

  • Będzie szybciej. Głównie dlatego, że tak naprawdę nie muszę uruchamiać nowych procesów dla wielu rzeczy, które chcę robić (basename i dirname są najbardziej oczywistymi przykładami, ale ogólnie można również wyeliminować wycinanie, grep, sortowanie i wc).
  • Obsługa ciągów w bashu jest w najlepszym wypadku szczątkowa, a cała sprawa $ IFS jest super-niezgrabna.
  • Warunki w skryptach powłoki mogą być nieporadne.
  • Cytowanie w skryptach powłoki może być koszmarem.
  • Instrukcja bash pozostawia wiele do życzenia poza prostymi przypadkami (NPI).
  • Tablice w bash suck. Hashe w bashu (zakładając, że twój bash jest wystarczająco nowy, aby je w ogóle mieć) ssać jeszcze mocniej.
  • Gdy przetwarzanie plików lub danych wyjściowych poleceń wykracza poza prosty przypadek wymieniony powyżej, Perl zaczyna naprawdę palić bash.
  • CPAN.

Więc to nie tak, że bash przejmie wkrótce Perla. Ale wciąż po tych wszystkich latach stwierdzam, że wiele razy prosty skrypt powłoki może czasami być prostszy niż prosty skrypt Perla. Jak mówię, z zadowoleniem przyjmuję wszelkie próby przekonania mnie do czegoś innego. Ale z drugiej strony nie ma nic złego w posiadaniu kilku różnych narzędzi w przyborniku.

buzz3791
źródło
Co ciekawe, w Ruby wszystkie (?) Punkty nie mają zastosowania, ponieważ Ruby ma at_exit (), realpath (), expand_path (), stat (), heredocs i wyjątki ( fail "error" unless system("foobar")).
Cezary Baginski
5

Z mojego doświadczenia wynika, że ​​bash kontra python to kompromis między czasem programowania a elastycznością. Podstawowe rozwiązanie problemu można zwykle ustalić w skrypcie bash szybciej niż w skrypcie python.

Python sprawi, że będziesz myślał bardziej o strukturze swojego rozwiązania niż o równoważnym skrypcie bash. Python ma bardziej ekspresyjną moc niż skrypt bash, więc z czasem lepiej się skaluje i modyfikuje. Jest również ogólnie bardziej czytelny.

Bash jest bliższy systemowi plików i może być świetny do pierwszego rozwiązania problemów, które NIE są dobrze zdefiniowane. Z tego powodu skrypt bash może być dobrym pierwszym wyborem do prototypowania czegoś z pełną intencją przeniesienia go do Pythona, gdy problem zostanie lepiej zrozumiany.

Travis
źródło
4

Bash jest powłoką uniksową, zawiera język skryptowy. Jest to raczej procesor poleceń. kontrolujesz sposób uruchamiania poleceń, faktycznie je uruchamiasz.

Perl / Ruby / Python to języki ogólnego przeznaczenia.

Kiedy potrzebujesz skryptu powłoki, używasz Bash

Jeśli chcesz bardziej złożone zadanie lub nie jest ono związane z powłoką. Użyj Python itp.

Nigdy nie porównałbym tych języków. Python itp. Są przenośne. Możesz je uruchomić w dowolnym miejscu. Bash jest tylko dla Uniksa.

Python itp. Ma mnóstwo bibliotek wielokrotnego użytku rozwiązujących miliony zadań.

To prawie to samo, jeśli pytasz. „Kiedy używać Paint, a kiedy Photoshop”

Do przetwarzania e-maili ponownie użyłbym Ruby, ponieważ ma wiele bibliotek wielokrotnego użytku.

Ale najlepszym sposobem byłoby połączenie bashu i rubinu. Tak by było. Podobnie jak w przypadku tworzenia skryptu przetwarzania wiadomości e-mail w skrypcie ruby, skrypt bash wywoła ten skrypt ruby ​​i uruchomi inne komendy ds.

Więc kiedy potrzebujesz procesora poleceń, używasz bash. Uruchamiasz polecenia Unix i kontrolujesz je.

AKTUALIZACJA po 7 latach (marzec 2019)

Chociaż główna część mojej odpowiedzi nie uległa zmianie, chciałbym to podkreślić.

Bash jest również potężnym językiem skryptowym. W przypadku przetwarzania tekstu może to być absolutnie uzasadniony wybór.

Przeczytaj komentarze mkaito poniżej. Wszystkie są całkowicie prawdziwe.

bakytn
źródło
1
Podzbiór skryptów Basha jest tak samo ogólny, jak każdy język skryptowy ogólnego przeznaczenia. Dodaj do miksu programy ogólne, takie jak sed, a uzyskasz 90% wszystkich potrzeb związanych ze skryptami.
mkaito,
1
bash jest procesorem poleceń, więc jego moc polega na uruchamianiu innych poleceń i programów uniksowych w ich skryptach. jak wspomniałeś sed itp.
Pyta,
1
Powłoka jest naprawdę świetnym programem do uruchamiania programów, ale jej możliwości skryptowe są znacznie większe. Proponuję nauczyć się prawdziwego skryptu powłoki.
mkaito,
Mogę spać na podłodze, ale wolałbym to robić na łóżku. Języki, których nie można porównać, mają różne cele.
bakytn
2
Cóż, jeśli Bash jest podłogą, coś takiego jak Haskell musi być gwoździem :-)
mkaito
1

Skrypty powłoki, takie jak bash, ksh, zsh, sh i fish, są niezwykle zaskakujące w porównaniu do języków ogólnego przeznaczenia wysokiego poziomu, takich jak Ruby, Python lub Perl. Podczas gdy skrypt powłoki może zacząć działać jako plik krótszy niż równoważny skrypt ogólnego przeznaczenia, niespodzianki prowadzą do wielu defensywnych kodów opakowaniowych, takich jak set -euo pipefailwłączenie trybów ścisłych.

Na przykład większość języków powłoki kontynuuje wykonywanie wierszy w skrypcie powłoki, nawet jeśli jedno z poleceń nie powiedzie się. Natomiast język ogólnego przeznaczenia natychmiast zawiesza się przy pierwszym błędzie i często jest obciążony, co skutkuje bezpieczniejszym, bardziej przewidywalnym zachowaniem w skryptach o nawet niewielkiej złożoności.

Mcandre
źródło
1

Bardzo stronniczy artykuł.

Nie uważam, żeby bash był tak trudny do debugowania. Python jest często zbyt sztywny, a bash pozwala być bardzo kreatywnym. Jeśli jesteś dobrym, nieszablonowym myślicielem, spodoba ci się bash.

Uruchamiam skrypty bash na milionach odczytów sekwencjonowania DNA w tysiącach plików, i to mi w porządku. I w przeciwieństwie do tego, co wszyscy mówią, te same wersje skryptów w C ++ nie działają tak dużo szybciej (po kilku minutach oddzielają je).

Myślę, że bash, podobnie jak perl, nie jest najbardziej przyjazny dla użytkownika / łatwy do odczytania. To odstrasza ludzi, ponieważ większość ludzi nie jest wielkimi myślicielami abstrakcyjnymi. Ale jaśniejsi, bardziej kreatywni programiści lubią to i często z niej korzystają. Jeśli znasz siebie i wiesz, że masz mózg, nie bój się bash. Jeśli jesteś podstawowym myślicielem, może trzymaj się czegoś takiego jak Python. Do każdego własnego.

CK
źródło
0

Z „Lamy Book”

Perl próbuje wypełnić lukę między programowaniem niskiego poziomu (np. W C lub C ++ lub asemblerze) a programowaniem wysokiego poziomu (takim jak programowanie „powłoki” [np. bash]). Programowanie na niskim poziomie jest zwykle trudne do napisania i brzydkie, ale szybkie i nieograniczone; trudno jest pokonać szybkość dobrze napisanego programu niskiego poziomu na danym komputerze. I niewiele tam można zrobić. Z drugiej strony programowanie na wysokim poziomie jest powolne, trudne, brzydkie i ograniczone; jest wiele rzeczy, których w ogóle nie można zrobić z programowaniem powłoki lub wsadowym, jeśli w systemie nie ma komendy zapewniającej wymaganą funkcjonalność. Perl jest łatwy, prawie nieograniczony, głównie szybki i trochę brzydki.

Geremia
źródło
0

Zasadniczo używaj najprostszego języka, który ma wystarczającą wydajność do wykonania zadania. A jego szczególne cechy tylko w takim stopniu, że są naprawdę przydatne.

A jeśli chodzi o czytelność, Bash jest okropny, jeśli twój styl programowania jest okropny. Jeśli po prostu rzucisz tam kod, staje się on niejasny.

Ale jeśli podzielisz kod na najkrótsze funkcje i nazwiesz rzeczy w prosty, zrozumiały sposób, będzie to najczystszy język, jaki możesz znaleźć. Ponieważ to jest bardzo zwięzłe.

Jak na przykład jest to mój najnowszy kod w Bash. Zauważ, jak łatwo to zrozumieć i wpisać:

#! /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 "${@}"
Alberto Salvia Novella
źródło