Como implementar idiomas bash comuns em Python? [fechadas]

242

Atualmente, faço minha manipulação de arquivos de texto através de um monte de AWK, sed, Bash e um pouco de Perl, muito lembrados.

Já vi mencionar alguns lugares que python é bom para esse tipo de coisa. Como posso usar o Python para substituir scripts de shell, AWK, sed e amigos?

Chris Jefferson
fonte
3
pythonpy é um bom concorrente para o awk e sed usando a sintaxe python: github.com/Russell91/pythonpy
RussellStewart
4
você pode usar shellpy que foi projetado com uma idéia em mente para substituir bash / sh com python github.com/lamerman/shellpy
Alexander Ponomarev
Esta é a minha pergunta, não entendo por que é baseada em opiniões. A resposta principal lista cada uma das principais coisas que um shell faz e informa como fazê-las em python. Isso, na minha opinião, responde à pergunta de maneira não opinativa.
91118 Chris Jefferson
Esta questão, e do fechamento, estão sendo discutidas na meta aqui
Erik A

Respostas:

144

Qualquer shell possui vários conjuntos de recursos.

  • Os comandos Essential Linux / Unix. Tudo isso está disponível na biblioteca de subprocessos . Essa nem sempre é a melhor primeira opção para executar todos os comandos externos. Observe também no shutil alguns comandos que são comandos separados do Linux, mas você provavelmente poderia implementar diretamente em seus scripts Python. Outro lote enorme de comandos do Linux está na biblioteca do sistema operacional ; você pode fazer isso de maneira mais simples no Python.

    E - bônus! -- mais rapidamente. Cada comando Linux separado no shell (com algumas exceções) bifurca um subprocesso. Usando Python shutile osmódulos, você não bifurca um subprocesso.

  • Os recursos do ambiente shell. Isso inclui itens que definem o ambiente de um comando (diretório atual e variáveis ​​de ambiente e o que não). Você pode gerenciar isso facilmente do Python diretamente.

  • Os recursos de programação do shell. Essa é toda a verificação do código de status do processo, os vários comandos lógicos (se, enquanto, para etc.) o comando test e todos os seus parentes. O material de definição de função. Tudo isso é muito, muito mais fácil no Python. Essa é uma das grandes vitórias em se livrar do bash e fazê-lo em Python.

  • Recursos de interação. Isso inclui o histórico de comandos e outros itens. Você não precisa disso para escrever scripts de shell. Isso é apenas para interação humana, e não para a escrita de scripts.

  • Os recursos de gerenciamento de arquivos shell. Isso inclui redirecionamento e pipelines. Isso é mais complicado. Muito disso pode ser feito com o subprocesso. Mas algumas coisas que são fáceis no shell são desagradáveis ​​no Python. Especificamente coisas como (a | b; c ) | something >result. Isso executa dois processos em paralelo (com saída de acomo entrada para b), seguido por um terceiro processo. A saída dessa sequência é executada em paralelo somethinge a saída é coletada em um arquivo chamado result. Isso é complexo de se expressar em qualquer outro idioma.

Programas específicos (awk, sed, grep etc.) geralmente podem ser reescritos como módulos Python. Não exagere. Substitua o que você precisa e evolua seu módulo "grep". Não comece escrevendo um módulo Python que substitua "grep".

A melhor coisa é que você pode fazer isso em etapas.

  1. Substitua AWK e PERL por Python. Deixe tudo o resto em paz.
  2. Observe a substituição do GREP pelo Python. Isso pode ser um pouco mais complexo, mas sua versão do GREP pode ser adaptada às suas necessidades de processamento.
  3. Observe a substituição do FIND por loops Python usados os.walk. Esta é uma grande vitória, porque você não gera tantos processos.
  4. Observe a substituição da lógica comum do shell (loops, decisões, etc.) por scripts Python.
S.Lott
fonte
6
escreveu: "Recursos de interação. Isso inclui o histórico de comandos e outros itens. Você não precisa disso." Receio que ninguém possa dizer o que uma pessoa realmente precisa ou não. Talvez ele faça. Além disso, essas instalações fazem muito sentido em um shell interativo, tomando como exemplo a diferença entre Idle e IPython.
21411 heltonbiker
47
Eu sinceramente gostaria que as pessoas abandonassem completamente os scripts de shell. Entendo que o hacking é praticamente uma religião no mundo * nix, mas me canso de tentar interpretar todas as soluções alternativas hackeadas implantadas no sistema operacional. A novidade dos microtools (awk, sed, top, base, etc) desapareceu no dia em que todos decidiram lançar sua própria versão. Eu me arrepio quando imagino a quantidade de horas de trabalho desperdiçada em pequenas ferramentas ruins que poderiam ser facilmente substituídas por alguns módulos Python bem projetados. :: sigh ::
Evan Plaice
40
Eu discordo do @EvanPlaice porque a versão em python de vários findscripts que tenho é feia, longa e não sustentável em comparação. Muitas coisas devem ser scripts de shell, muitas outras não . Nem tudo precisa ser apenas um de Python ou BASH (ou qualquer outra coisa).
Mikebabcock #
8
@mikebabcock Idealmente, haveria uma biblioteca completa que implementa todas as micro-ferramentas disponibilizadas pela pilha básica * nix. Funções como find () e last () seriam incluídas e, em vez de tubos, uma combinação de currying e carregamento preguiçoso lidaria com a colagem. Não seria bom ter um ambiente de script POSIX que funcione de maneira padrão em todas as distros? Nada como isso existe, ainda ... #
315 Evan
2
O ponto sobre shell pipelines (tais como (a | b; c ) | something >result) é algo mitigada por ela ser trivialmente fácil passar condutas de casca de subprocessmétodos que utilizemshell=True
Iruvar
103

Sim, claro :)

Dê uma olhada nessas bibliotecas que o ajudam a nunca escrever scripts de shell novamente (lema do Plumbum).

Além disso, se você deseja substituir o awk, sed e grep por algo baseado em Python, recomendo o pyp -

"The Pyed Piper", ou pyp, é uma ferramenta de manipulação de texto de linha de comando do linux semelhante ao awk ou sed, mas que usa os métodos padrão de lista e seqüência de caracteres python, bem como funções personalizadas desenvolvidas para gerar resultados rápidos em um ambiente de produção intenso.

Piotr Dobrogost
fonte
Veja também o Envoy, que é uma alternativa para sh github.com/kennethreitz/envoy
AllanLRH
57

Acabei de descobrir como combinar as melhores partes do bash e do ipython. Até agora, isso me parece mais confortável do que usar subprocessos e assim por diante. Você pode copiar facilmente grandes partes dos scripts bash existentes e, por exemplo, adicionar tratamento de erros da maneira python :) E aqui está o meu resultado:

#!/usr/bin/env ipython3

# *** How to have the most comfort scripting experience of your life ***
# ######################################################################
#
# … by using ipython for scripting combined with subcommands from bash!
#
# 1. echo "#!/usr/bin/env ipython3" > scriptname.ipy    # creates new ipy-file
#
# 2. chmod +x scriptname.ipy                            # make in executable
#
# 3. starting with line 2, write normal python or do some of
#    the ! magic of ipython, so that you can use unix commands
#    within python and even assign their output to a variable via
#    var = !cmd1 | cmd2 | cmd3                          # enjoy ;)
#
# 4. run via ./scriptname.ipy - if it fails with recognizing % and !
#    but parses raw python fine, please check again for the .ipy suffix

# ugly example, please go and find more in the wild
files = !ls *.* | grep "y"
for file in files:
  !echo $file | grep "p"
# sorry for this nonsense example ;)

Consulte a documentação do IPython sobre os comandos do shell do sistema e use-o como um shell do sistema .

O K
fonte
11
Promovido porque por alguma razão bizarra, ninguém mais mencionou! -Mandos no IPython, que são absolutamente essenciais; especialmente desde que você também pode atribuir a sua saída para uma variável (lista de linhas) como emfilelines = ! cat myfile
Kampu
E você pode usar variáveis ​​python como $varem um comando shell? Uau. Essa deve ser a resposta aceita.
Chiel ten Brinke 17/03/16
E você também pode usá-lo a partir de dentro dos cadernos jupyter
Yuval Atzmon
44

A partir de 2015 e do lançamento do Python 3.4, agora existe um shell interativo do usuário razoavelmente completo disponível em: http://xon.sh/ ou https://github.com/scopatz/xonsh

O vídeo de demonstração não mostra os tubos sendo usados, mas eles são suportados no modo de shell padrão.

O Xonsh ('concha') se esforça muito para imitar o bash, então coisas pelas quais você já ganhou memória muscular, como

env | uniq | sort -r | grep PATH

ou

my-web-server 2>&1 | my-log-sorter

ainda funcionará bem.

O tutorial é bastante longo e parece cobrir uma quantidade significativa da funcionalidade que alguém normalmente esperaria em um prompt do ash ou do bash:

  • Compila, avalia e executa!
  • Histórico de comandos e conclusão de guias
  • Ajuda e superajuda com ?&??
  • Aliases e prompts personalizados
  • Executa comandos e / ou *.xshscripts que também podem ser importados
  • Variáveis ​​de ambiente, incluindo pesquisa com ${}
  • Redirecionamento e combinação de entrada / saída
  • Trabalhos em segundo plano e controle de trabalhos
  • Aninhando subprocessos, tubulações e coprocessos
  • Modo subprocesso quando existe um comando, modo Python, caso contrário
  • Subprocesso Capturado com $(), Subprocesso Não Capturado com $[], Avaliação Python com@()
  • Nome do arquivo globbing com *ou expressão regular Nome do arquivo globbing com backticks
Kamilion
fonte
Mas por que parece que todas essas respostas estão apenas reinventando a roda para pessoas que não conhecem o bash ? Fiquei moderadamente confortável com o bash e cada uma dessas respostas parece que acabará sendo mais trabalhosa por pouco benefício. Essas respostas são todas voltadas para pessoas em python que têm medo (ou não querem gastar tempo aprendendo) do bash, estou certo?
Buttle Butkus
Parece ter algumas desvantagens, como requisito para usar a .xshextensão para arquivos com o código xonsh : github.com/xonsh/xonsh/issues/2478 . Caso contrário, você precisará usá evalx-lo para chamá-lo diretamente dos .pyarquivos.
Andry
31
  • Se você deseja usar o Python como um shell, por que não dar uma olhada no IPython ? Também é bom aprender interativamente o idioma.
  • Se você faz muita manipulação de texto e se usa o Vim como editor de texto, também pode escrever diretamente plugins para o Vim em python. basta digitar ": help python" no Vim e siga as instruções ou veja esta apresentação . É tão fácil e poderoso escrever funções que você usará diretamente no seu editor!
Mapad
fonte
8
existe um perfil ipython chamado 'sh' que torna o interpretador muito parecido com um shell.
24509 Autoplectic
3
O perfil ipython 'sh' foi removido há algum tempo.
Gdw2
>>> resultado =! dmesg | grep -i 'usb' #the! operador faz tudo
Permafacture
16

No começo havia sh, sed e awk (e encontre, e grep, e ...). Foi bom. Mas o awk pode ser um animal estranho e difícil de lembrar se você não o usa com frequência. Então o grande camelo criou Perl. Perl era o sonho de um administrador de sistemas. Era como um script de shell com esteróides. O processamento de texto, incluindo expressões regulares, era apenas parte do idioma. Então ficou feio ... As pessoas tentaram fazer grandes aplicações com o Perl. Agora, não me interpretem mal, o Perl pode ser um aplicativo, mas pode (pode!) Parecer uma bagunça se você não for realmente cuidadoso. Depois, há todo esse negócio de dados planos. É o suficiente para enlouquecer um programador.

Digite Python, Ruby, et al. Essas são realmente muito boas linguagens de uso geral. Eles suportam o processamento de texto e o fazem bem (embora talvez não esteja tão entrelaçado no núcleo básico da linguagem). Mas eles também aumentam muito bem e ainda têm um código bonito no final do dia. Eles também desenvolveram comunidades bastante pesadas, com muitas bibliotecas para quase tudo.

Agora, grande parte da negatividade em relação ao Perl é uma questão de opinião, e certamente algumas pessoas podem escrever um Perl muito limpo, mas com tantas pessoas reclamando que é muito fácil criar código ofuscado, você sabe que existe alguma verdade. A questão realmente se torna: você alguma vez usará essa linguagem para mais do que simples substituições de scripts do bash. Se não, aprenda um pouco mais de Perl ... é absolutamente fantástico para isso. Se, por outro lado, você quiser uma linguagem que cresça com você, como você deseja fazer mais, sugiro Python ou Ruby.

De qualquer maneira, boa sorte!

MattG
fonte
9

Sugiro o incrível livro on-line Dive Into Python . Foi assim que aprendi o idioma originalmente.

Além de ensinar a estrutura básica da linguagem e várias estruturas de dados úteis, possui um bom capítulo sobre manipulação de arquivos e capítulos subsequentes sobre expressões regulares e muito mais.

Dan Lenski
fonte
1
... questão principal de respostas somente para links.
Jean-François Fabre
7

Adicionando respostas anteriores: verifique o módulo pexpect para lidar com comandos interativos (adduser, passwd etc.)

Federico A. Ramponi
fonte
7

Uma razão pela qual eu amo o Python é que ele é muito melhor padronizado do que as ferramentas POSIX. Eu tenho que verificar duas vezes e três vezes se cada bit é compatível com outros sistemas operacionais. Um programa gravado em um sistema Linux pode não funcionar da mesma maneira em um sistema BSD do OSX. Com o Python, basta verificar se o sistema de destino possui uma versão suficientemente moderna do Python.

Melhor ainda, um programa escrito em Python padrão será executado no Windows!

Hal Canary
fonte
1
"um programa escrito em Python padrão roda no Windows": sem brincadeira?
Jean-François Fabre
6

Vou dar aqui minha opinião com base na experiência:

Para casca:

  • O shell pode gerar muito facilmente código somente leitura. Escreva e, quando voltar, nunca descobrirá o que fez novamente. É muito fácil conseguir isso.
  • shell pode fazer MUITO processamento de texto, divisão, etc em uma linha com tubos.
  • é a melhor linguagem de cola quando se trata de integrar a chamada de programas em diferentes linguagens de programação.

Para python:

  • se você quiser portabilidade para o Windows, use python.
  • python pode ser melhor quando você precisa manipular pouco mais que texto, como coleções de números. Para isso, eu recomendo python.

Normalmente, escolho o bash para a maioria das coisas, mas quando tenho algo que deve cruzar os limites do Windows, apenas uso python.

Germán Diago
fonte
4

pythonpy é uma ferramenta que fornece acesso fácil a muitos dos recursos do awk e sed, mas usando a sintaxe python:

$ echo me2 | py -x 're.sub("me", "you", x)'
you2
RussellStewart
fonte
3

Eu construí scripts shell semi-longos (300-500 linhas) e código Python, que possui funcionalidade semelhante. Quando muitos comandos externos estão sendo executados, acho que o shell é mais fácil de usar. Perl também é uma boa opção quando há muita manipulação de texto.

Mike Davis
fonte
3

Ao pesquisar este tópico, encontrei este código de prova de conceito (através de um comentário em http://jlebar.com/2010/2/1/Replacing_Bash.html ) que permite "escrever pipelines semelhantes a shell em Python usando um sintaxe concisa e aproveitando as ferramentas de sistema existentes onde elas fazem sentido ":

for line in sh("cat /tmp/junk2") | cut(d=',',f=1) | 'sort' | uniq:
    sys.stdout.write(line)
Nickolay
fonte
2

Sua melhor aposta é uma ferramenta voltada especificamente para o seu problema. Se estiver processando arquivos de texto, Sed, Awk e Perl são os principais candidatos. Python é uma linguagem dinâmica de uso geral . Como em qualquer linguagem de uso geral, há suporte para manipulação de arquivos, mas não é esse o objetivo principal. Eu consideraria Python ou Ruby se tivesse um requisito para uma linguagem dinâmica em particular.

Em resumo, aprenda muito bem o Sed e o Awk, além de todos os outros itens que acompanham o seu sabor de * nix (todos os built-ins do Bash, grep, tr e assim por diante). Se você está interessado no processamento de arquivos de texto, já está usando as coisas certas.

Eric Smith
fonte
2

Você pode usar python em vez de bash com a biblioteca ShellPy .

Aqui está um exemplo que baixa o avatar do usuário Python no Github:

import json
import os
import tempfile

# get the api answer with curl
answer = `curl https://api.github.com/users/python
# syntactic sugar for checking returncode of executed process for zero
if answer:
    answer_json = json.loads(answer.stdout)
    avatar_url = answer_json['avatar_url']

    destination = os.path.join(tempfile.gettempdir(), 'python.png')

    # execute curl once again, this time to get the image
    result = `curl {avatar_url} > {destination}
    if result:
        # if there were no problems show the file
        p`ls -l {destination}
    else:
        print('Failed to download avatar')

    print('Avatar downloaded')
else:
    print('Failed to access github api')

Como você pode ver, todas as expressões dentro do símbolo grave acento (`) são executadas no shell. E no código Python, você pode capturar resultados dessa execução e executar ações nela. Por exemplo:

log = `git log --pretty=oneline --grep='Create'

Essa linha será executada primeiro git log --pretty=oneline --grep='Create'no shell e depois atribuirá o resultado à variável de log. O resultado possui as seguintes propriedades:

stdout o texto inteiro do stdout do processo executado

stderr o texto inteiro do stderr do processo executado

returncode returncode da execução

Esta é uma visão geral da biblioteca; descrição mais detalhada com exemplos pode ser encontrada aqui .

Alexander Ponomarev
fonte
1

Se sua manipulação de arquivo de texto geralmente é única, possivelmente feita no prompt do shell, você não obterá nada melhor do python.

Por outro lado, se você normalmente precisa executar a mesma tarefa (ou semelhante) repetidamente e precisa escrever seus scripts para fazer isso, o python é ótimo - e você pode criar facilmente suas próprias bibliotecas (você pode isso também com scripts de shell, mas é mais complicado).

Um exemplo muito simples de entender.

import popen2
stdout_text, stdin_text=popen2.popen2("your-shell-command-here")
for line in stdout_text:
  if line.startswith("#"):
    pass
  else
    jobID=int(line.split(",")[0].split()[1].lstrip("<").rstrip(">"))
    # do something with jobID

Verifique também o sys e o módulo getopt, pois eles são os primeiros que você precisará.

Davide
fonte
1

Eu publiquei um pacote em PyPI: ez .
Use pip install ezpara instalá-lo.

Ele empacotou comandos comuns no shell e muito bem minha lib usa basicamente a mesma sintaxe do shell. por exemplo, cp (origem, destino) pode lidar com arquivos e pastas! (wrapper de shutil.copy shutil.copytree e decide quando usar qual). Ainda melhor, ele pode suportar a vetorização como o R!

Outro exemplo: no os.walk, use fls (path, regex) para localizar recursivamente arquivos e filtrar com expressões regulares e ele retorna uma lista de arquivos com ou sem o caminho completo

Exemplo final: você pode combiná-los para escrever scripts muito simples:
files = fls('.','py$'); cp(files, myDir)

Definitivamente, confira! Me custou centenas de horas para escrever / melhorar!

Jerry T
fonte
1
Parece interessante, mas não posso analisar os documentos não formatados em pypi.python.org/pypi/ez , desculpe ...
Greg Dubicki