Quando usar o Bash e quando usar Perl / Python / Ruby? [fechadas]

78

Até agora, estamos fazendo todos os nossos scripts com o Bash, mas estou começando a me sentir um pouco bobo. Embora possamos, obviamente, fazer tudo o que queremos com o Bash (é bastante poderoso), estou começando a me perguntar se não devemos usar uma linguagem de script adequada (no nosso caso, provavelmente Ruby).

Como você decide quando usar Perl / Python / Ruby sobre Bash para um script? Não acho que um script init com Ruby faça sentido, mas que tal um script um pouco mais longo que adicione contas de email?

futlib
fonte
11
Se você pode fazer isso usando qualquer um, isso realmente importa? A escolha é interessante apenas se o script resultante apresentar alguma diferença. Por exemplo, o tempo de execução pode diferir drasticamente (não é um problema nas contas de email).
Dennis

Respostas:

44

Dado um problema que ambos podem resolver, convém usar o que você mais se sentir confortável. Por fim, existem muitos pequenos detalhes e apenas a experiência pode ensiná-lo a vê-los.

O Bash é uma linguagem de script de uso geral, como Python, Ruby, Perl, mas cada uma possui pontos fortes diferentes do restante. Perl se destaca na análise de texto, o Python afirma ser o mais elegante do grupo, os scripts Bash são excelentes para "entender", se você entende o que quero dizer, e Ruby ... bem, Ruby é um pouco especial em muitos aspectos de maneiras.

No entanto, as diferenças entre eles só importam quando você tem uma boa experiência em scripts. Sugiro que você escolha um idioma e coloque-o nos limites antes de passar para o próximo. Você pode fazer muito em um script de shell, mais do que a maioria das pessoas admitiria. Qualquer idioma é tão difícil quanto você deseja. Depois de escrever algumas coisas, todo idioma é "fácil" para você.

Estar familiarizado com o shell compensa rapidamente se você mora no Linux, então talvez você queira começar com isso. Se você encontrar uma tarefa impossível ou impraticável para resolver em um script de shell, use outra coisa.

Além disso, lembre-se de que aprender scripts de shell é muito simples. O verdadeiro poder disso reside em outros programas, como awk, sed, tr, et al.

mkaito
fonte
Eu tenho bastante experiência com scripts bash, como no Ruby, mas às vezes ainda não sei o que usar. Escolher com base na preferência pessoal naquele momento parece tolo. Mas você está certo, vou me perguntar o que quero fazer e escolher a melhor ferramenta para o trabalho.
futlib
Pessoalmente, usarei uma escala das linguagens que conheço bem, em ordem crescente de complexidade e poder, e usarei as mais simples que atendam às exigências. Mas, na verdade, a única maneira de saber com certeza é escrever seu script em todos os idiomas e comparar o resultado. É tudo mais um pressentimento do que uma certeza. Depois de alguns anos escrevendo scripts, você terá encontrado a maioria dos "tipos de problemas" e saberá qual idioma os resolveu bem.
Mkpel
Só queria acrescentar que, usando pequenos programas no pacote coreutils do GNU (como tr, sort, uniq) e encanando-os, é possível realizar muitas tarefas.
GMaster 11/01
58

TL; DR - use o bash apenas para instalar um idioma melhor (se ainda não estiver disponível); caso contrário, você estará perdendo um tempo humano irrecuperável e precioso. Se você não pode fazê-lo na linha de comando manualmente, sem erros, não faça scripts com o bash / shell.

É 2015, então eu consideraria o seguinte:

  1. sobrecarga de memória

    • A sobrecarga de memória de tempo de execução Ruby / Python em comparação com o bash é pequena (por causa de bibliotecas compartilhadas), enquanto provavelmente não é possível manter um script de bash não trivial de qualquer maneira (por exemplo, um com> 100 linhas) - portanto, o uso da memória não é um fator
  2. hora de inicialização

    • A inicialização do Ruby / Python pode ser um pouco mais lenta, mas é provável que você não esteja executando muitos processos completos do Ruby / Python em um loop apertado 100 vezes por segundo (se você tiver esse tipo de necessidade, o bash / shell é muita sobrecarga de qualquer maneira e você provavelmente precisará passar para C / C ++)
  3. desempenho

    • quase todo o processamento de dados típico será mais rápido em Ruby / Python - ou pelo menos comparável (ou, você precisa de C / C ++ / Haskel / OCaml / qualquer que seja)
    • o real desempenho / gargalo na execução (ou mesmo produtividade) quase nunca será "uma falta de uso do bash / shell" (até o traço de comutação do Ubuntu para inicialização mostra como o bash é realmente o problema - e um busybox é provavelmente o único caso de uso , porque não nada além de 'bash' e 'vi' para escrever e executar código, e geralmente não há como adicionar / baixar ou armazenar qualquer outra coisa)
    • executar outros processos para fazer o trabalho (como sed / awk / grep) é na verdade uma magnitude mais lenta do que chamar um método em um objeto ativo na memória
  4. produtividade

    • é muito fácil cometer erros no Bash / shell em comparação ao uso de métodos, parâmetros, variáveis ​​e exceções "reais" no Ruby / Python
    • O Agile é mainstream, enquanto o Bash não tem suporte para ele (falta de recursos de teste de unidade, bibliotecas, OO, modularidade, linting, introspecção, log, metaprogramação; quase impossível refatorar sem quebrar nada)
    • Com muitas incompatibilidades com outros shells, as variáveis ​​de ambiente menores podem quebrar completamente um script (e algumas ferramentas importantes de desenvolvimento, como o Puppet, ignoram as linhas shebang e transmitem ou reescrevem variáveis ​​importantes do shell), enquanto o Ruby / Python possui uma migração relativamente suave bem definida caminhos mesmo para grandes alterações de versão
    • aprender um novo idioma leva uma fração do tempo gasto depurando os scripts do shell devido a problemas específicos do shell (notavelmente - nomes de variáveis, sem booleanos, sem exceções, etc.)
    • até scripts de inicialização são uma mina terrestre ( especialmente porque podem falhar durante a inicialização do sistema ) e, dadas as recentes falhas de segurança com o bash, é melhor usar C simples (com boas bibliotecas) - sim, C precisa de compilação, configuração etc. , mas mesmo um script de shell simples pode precisar de um repositório, versão e empacotamento de qualquer maneira.
    • o que estiver disponível com o sed / awk / grep provavelmente já está embutido no Ruby / Python - sem que seja uma dependência ou "diferenças" entre as versões dessas ferramentas nas plataformas (e daí se funcionar na sua configuração)
  5. seguro desemprego
    • qual o sentido de garantir um emprego que você não gosta? (a menos que você goste de passar todas aquelas horas difíceis de depurar, mas triviais de criar scripts de shell)

Acho que não há razão para usar o Bash / Shell se você tiver o Ruby / Python instalado.

E provavelmente instalar o Ruby / Python nem sequer precisa de um script bash (com exceção do busybox, algumas ferramentas do sistema dependem da presença do Python / Perl).

E toda vez que você escreve um script de shell, está "praticando" fazendo exatamente isso - em vez de aprender algo mais poderoso / produtivo.

Por que as pessoas usam o Bash hoje em dia? Porque é um hábito terrível e difícil de quebrar. Um script raramente é "terminado para sempre" após os primeiros minutos - não importa o quão fortemente as pessoas pensem dessa maneira. Juntamente com a falácia "é o último bug deste script".

Conclusão: use o bash / shell somente quando estiver absolutamente forçado a (como o ~/.bashrcbusybox), porque quase nunca é "a ferramenta certa para o trabalho" hoje em dia.

Cezary Baginski
fonte
28

Uso o bash quando meu foco principal é o manuseio de arquivos. Isso pode incluir mover, copiar e renomear arquivos, além de usar arquivos como entrada para outros programas ou armazenar a saída de outros programas em arquivos. Eu raramente escrevo código bash que realmente examina o conteúdo de um arquivo ou gera a saída para gravar em um arquivo; Deixo isso para os outros programas (que posso escrever em Perl ou python) que inicio via bash.

Uso Perl e python quando meu foco principal é ler dados de arquivos, processar esses dados de alguma maneira e gravar a saída em arquivos. Se eu me encontrar usando (em Perl) o systemcomando, back ticks ou (em python) o subprocessmódulo muito extensivamente, considero escrever o script no bash. Por outro lado, às vezes começo a adicionar tanta funcionalidade a um script bash que, eventualmente, faz mais sentido reescrevê-lo em Perl / python, em vez de lidar com o suporte limitado (por comparação) do bash para escopo de variáveis, funções, estruturas de dados, etc. .

chepner
fonte
2
Eu costumava t0 também fiança em Bash sempre que foi necessário geração de arquivo de leitura / texto, mas depois de aprender o =~operador apoiado por [[ ]]eu ter sido me amar algum Bash para simples leitura de arquivos
Freedom_Ben
16

Gosto dos critérios estabelecidos nesta postagem do blog .

  • Se não houver argumentos a serem passados, provavelmente é um shell script.
  • Se não há muito para a lógica de controle (além de um único loop ou se / mais), provavelmente é um script de shell.
  • Se a tarefa é automatizar as instruções da linha de comando, é quase definitivamente um script de shell.
MarkTee
fonte
8

Achei essa análise Perl versus Bash útil ...

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

Por conveniência, estou copiando um resumo do autor 1) quando bash é uma descoberta melhor e 2) quando perl é uma conclusão melhor ...

Quando Bash é melhor ...

  • Falha no Trabalho
  • Comandos ao sair
  • Processando linhas de saída do trabalho
  • Aqui Documentos
  • Equivalências de arquivo
  • Comparações de data e hora do arquivo
  • Expansão Tilde

Quando Perl é melhor ...

Perl ainda é melhor do que o bash para a maioria das aplicações. Razões pelas quais eu prefiro o Perl incluem (mas não estão limitadas a):

  • Vai ser mais rápido. Principalmente porque eu realmente não tenho que iniciar novos processos para muitas das coisas que quero fazer (o nome da base e o nome do diretório são os exemplos mais óbvios, mas geralmente corte, grep, classificação e wc também podem ser eliminados).
  • O manuseio de cordas no bash é rudimentar, na melhor das hipóteses, e a coisa toda do $ IFS é super desajeitada.
  • Condicionais em scripts de shell podem ser instáveis.
  • A citação em scripts de shell pode ser um pesadelo.
  • A declaração de caso do bash deixa muito a desejar além dos casos simples (NPI).
  • Matrizes em bash sugam. Os hashes no bash (supondo que o bash seja novo o suficiente para tê-los) são mais difíceis.
  • Depois que o processamento de arquivos ou saída de comando vai além do caso simples que listei acima, o Perl começa a realmente fumar bash.
  • CPAN.

Portanto, não é como se o bash assumisse o Perl em breve. Mas ainda acho, depois de todos esses anos, que muitas vezes um simples shell script pode às vezes ser mais simples que um simples script Perl. Como digo, saúdo todas as tentativas de me convencer do contrário. Mas, novamente, não há nada errado em ter algumas ferramentas diferentes em sua caixa de ferramentas.

buzz3791
fonte
Curiosamente, em Ruby, todos os pontos (?) Não se aplicam, porque Ruby possui at_exit (), realpath (), expand_path (), stat (), heredocs e exceções ( fail "error" unless system("foobar")).
Cezary Baginski
5

Na minha experiência, bash versus python é uma troca entre tempo de desenvolvimento e flexibilidade. Uma solução rudimentar para um problema geralmente pode ser estabelecida em um script bash mais rapidamente do que em um script python.

O Python tenderá a fazer você pensar mais sobre a estrutura da sua solução do que o script bash equivalente. O Python tem um poder mais expressivo do que um script bash e, portanto, tende a escalar e modificar melhor ao longo do tempo. Também permanece mais legível em geral.

O Bash está mais próximo do sistema de arquivos e pode ser ótimo para as primeiras soluções de rascunho para problemas que NÃO estão bem definidos. Por esse motivo, um script bash pode ser uma boa primeira opção para prototipar algo com a intenção total de portá-lo para python, uma vez que o problema seja melhor compreendido.

Travis
fonte
4

Bash é um shell Unix que inclui uma linguagem de script. É bastante processador de comando. você controla a maneira como executa comandos, na verdade os executa.

Perl / Ruby / Python são linguagens de uso geral.

Quando você deseja um script de shell, usa o Bash

Se você deseja uma tarefa mais complexa ou não relacionada ao shell. Use Python etc.

Eu nunca compararia esses idiomas, na verdade. Python etc. são portáteis. Você pode executá-los em qualquer lugar. O Bash é apenas para Unix.

O Python etc. tem toneladas de bibliotecas reutilizáveis, resolvendo milhões de tarefas.

É quase o mesmo se você perguntar. "Quando usar o Paint e quando usar o Photoshop"

Para processar e-mails, eu usaria o Ruby novamente, porque ele possui muitas bibliotecas reutilizáveis.

Mas a melhor maneira seria combinar bash e ruby. Isso seria correto. Como se você criasse um script de processamento de email em ruby, o script bash invocaria esse script ruby ​​e executaria outros ds commans.

Portanto, sempre que você precisar de um processador de comando, use o bash. Você executa comandos unix e os controla.

ATUALIZAÇÃO após 7 anos (mar 2019)

Embora a parte principal da minha resposta não tenha mudado, gostaria de salientar isso.

O Bash também é uma linguagem de script poderosa. Para o processamento de texto, pode ser uma escolha legítima absoluta.

Por favor, leia os comentários de mkaito abaixo. Todos eles são completamente verdadeiros.

bakytn
fonte
11
O subconjunto de scripts do Bash é tão genérico quanto qualquer linguagem de script de uso geral. Adicione programas gerais como o sed à mistura, e você estará coberto por 90% de todas as necessidades de scripts que você jamais terá.
mkaito
11
bash é um processador de comando para que o seu poder é executar outros comandos Unix e programas em sua scripts.like você mencionou sed etc. Ele está pedindo para quando escolher determinada língua
bakytn
11
O shell é realmente um iniciador de programas glorificado, mas seus recursos de script estão muito além disso. Eu sugiro que você aprenda alguns scripts de shell reais.
Mkpel
Eu posso dormir no chão, mas eu prefiro fazê-lo na cama. As línguas não podem ser comparadas, têm propósitos diferentes.
bakytn
2
Bem, se Bash é o piso, algo como Haskell deve ser um :-) diagrama unifilar
mkaito
1

Scripts de shell como bash, ksh, zsh, sh e fish são notoriamente surpreendentes, em comparação com linguagens de alto nível de uso geral como Ruby, Python ou Perl. Embora um script de shell possa começar sua vida como um arquivo mais curto que o script de uso geral equivalente, as surpresas levam a muitos códigos de quebra defensivos, como set -euo pipefailhabilitar modos estritos.

Por exemplo, a maioria dos idiomas de shell continua executando linhas em um script de shell, mesmo quando um dos comandos falha. Por outro lado, uma linguagem de propósito geral falha imediatamente no primeiro erro e, muitas vezes, carregada, resultando em um comportamento mais seguro e previsível em scripts de complexidade ainda mais leve.

mcandre
fonte
1

Artigo altamente tendencioso.

Não acho que o bash seja tão difícil de depurar. O Python geralmente é muito rígido, enquanto o bash permite que você seja muito criativo. Se você é um bom pensador pronto para usar, vai gostar do bash.

Eu executo scripts bash em milhões de leituras de seqüenciamento de DNA em milhares de arquivos, e isso me serve muito bem. E, ao contrário do que todo mundo diz, as mesmas versões dos scripts em C ++ não são executadas muito mais rapidamente (em alguns minutos, separe-as).

Eu acho que o bash, como o perl, não é o mais amigável / fácil de ler. Isso assusta as pessoas, porque muitas pessoas não são grandes pensadoras abstratas. Porém, programadores mais brilhantes e criativos tendem a adorar e fazer uso frequente. Se você se conhece e sabe que tem um cérebro, não se assuste com a festança. Se você é um pensador básico, talvez se apegue a algo como Python. Para cada um deles.

CK
fonte
0

No "Livro da Lhama",

O Perl tenta preencher a lacuna entre a programação de baixo nível (como em C ou C ++ ou montagem) e a programação de alto nível (como a programação "shell" [por exemplo, bash]). A programação de baixo nível é geralmente difícil de escrever e feia, mas rápida e ilimitada; é difícil superar a velocidade de um programa de baixo nível bem escrito em uma determinada máquina. E não há muito que você não possa fazer lá. A programação de alto nível, no outro extremo, tende a ser lenta, difícil, feia e limitada; existem muitas coisas que você não pode fazer com a programação de shell ou de lote se não houver um comando no sistema que forneça a funcionalidade necessária. Perl é fácil, quase ilimitado, principalmente rápido e meio feio.

Geremia
fonte
0

Como regra geral, use o idioma mais simples que tenha um desempenho bom o suficiente para sua tarefa em mãos. E suas particularidades apenas na medida em que são realmente úteis.

E quanto à legibilidade, o Bash é horrível se seu estilo de programação é horrível. Se você simplesmente jogar código por lá, ele se torna obscuro.

Mas se você dividir o código nas funções mais curtas e nomear as coisas de uma maneira simples e compreensível, é a linguagem mais clara que você pode encontrar. Porque é muito conciso.

Como amostra, este é o meu código mais recente no Bash. Observe como é fácil entender e digitar:

#! /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
fonte