¿Cómo implementar modismos comunes de bash en Python? [cerrado]

242

Actualmente hago mi manipulación de archivos de texto a través de un montón de AWK, sed, Bash y un poquito de Perl.

He visto mencionar algunos lugares en los que Python es bueno para este tipo de cosas. ¿Cómo puedo usar Python para reemplazar el script de shell, AWK, sed y amigos?

Chris Jefferson
fuente
3
pythonpy es un buen competidor para awk y sed usando la sintaxis de python: github.com/Russell91/pythonpy
RussellStewart
44
puede usar shellpy que fue diseñado con una idea en mente para reemplazar bash / sh con python github.com/lamerman/shellpy
Alexander Ponomarev
Esta es mi pregunta, no entiendo por qué se basa en la opinión. La respuesta principal enumera cada una de las cosas principales que hace un shell y le dice cómo hacerlo en Python. Eso, en mi opinión, responde a la pregunta de una manera sin opinión.
Chris Jefferson
Esta pregunta, y su cierre, se están discutiendo en meta aquí
Erik A

Respuestas:

144

Cualquier shell tiene varios conjuntos de características.

  • Los comandos esenciales de Linux / Unix. Todos estos están disponibles a través de la biblioteca de subprocesos . Esta no siempre es la mejor primera opción para hacer todos los comandos externos. Mire también shutil para ver algunos comandos que son comandos separados de Linux, pero probablemente podría implementarlos directamente en sus scripts Python. Otra gran lote de comandos de Linux están en el sistema operativo de la biblioteca; puedes hacer esto más simplemente en Python.

    Y - bono! -- mas rapido. Cada comando separado de Linux en el shell (con algunas excepciones) bifurca un subproceso. Al usar Python shutily los osmódulos, no bifurca un subproceso.

  • Las características del entorno de shell. Esto incluye cosas que establecen el entorno de un comando (directorio actual y variables de entorno y qué no). Puede administrar esto fácilmente desde Python directamente.

  • Las características de programación de shell. Esta es toda la comprobación del código de estado del proceso, los diversos comandos lógicos (si, while, for, etc.), el comando de prueba y todos sus parientes. El material de definición de funciones. Todo esto es mucho, mucho más fácil en Python. Esta es una de las grandes victorias en deshacerse de bash y hacerlo en Python.

  • Características de interacción. Esto incluye el historial de comandos y lo que no. No necesita esto para escribir scripts de shell. Esto es solo para la interacción humana, y no para la escritura de guiones.

  • Las características de gestión de archivos de shell. Esto incluye la redirección y las tuberías. Esto es más complicado. Gran parte de esto se puede hacer con subproceso. Pero algunas cosas que son fáciles en el shell son desagradables en Python. Específicamente cosas como (a | b; c ) | something >result. Esto ejecuta dos procesos en paralelo (con salida acomo entrada b), seguido de un tercer proceso. La salida de esa secuencia se ejecuta en paralelo con somethingy la salida se recopila en un archivo llamado result. Eso es complejo de expresar en cualquier otro idioma.

Los programas específicos (awk, sed, grep, etc.) a menudo se pueden reescribir como módulos de Python. No te vayas por la borda. Reemplace lo que necesita y desarrolle su módulo "grep". No empieces a escribir un módulo de Python que reemplace "grep".

Lo mejor es que puedes hacer esto en pasos.

  1. Reemplace AWK y PERL con Python. Deja todo lo demás solo.
  2. Mira reemplazar GREP con Python. Esto puede ser un poco más complejo, pero su versión de GREP se puede adaptar a sus necesidades de procesamiento.
  3. Mira reemplazar FIND con bucles Python que usan os.walk. Esta es una gran victoria porque no genera tantos procesos.
  4. Observe reemplazar la lógica de shell común (bucles, decisiones, etc.) con scripts de Python.
S.Lott
fuente
66
escribió: "Características de interacción. Esto incluye el historial de comandos y lo que no. No necesita esto". Me temo que nadie podría decir lo que una persona realmente necesita o no. Quizás lo hace. Además, estas instalaciones tienen mucho sentido en un shell interactivo, tomando como ejemplo la diferencia entre Idle e IPython.
Heltonbiker
47
Deseo sinceramente que la gente abandone los scripts de shell por completo. Entiendo que la piratería es prácticamente una religión en el mundo * nix, pero me canso de tratar de interpretar todas las soluciones alternativas implacables implantadas en el sistema operativo. La novedad de los microtools (awk, sed, top, base, etc.) desapareció el día en que todos decidieron lanzar su propia versión. Me estremezco cuando imagino la cantidad de horas de trabajo desperdiciadas en pequeñas herramientas que podrían reemplazarse fácilmente por un par de módulos Python bien diseñados. :: suspiro ::
Evan Plaice
40
No estoy de acuerdo con @EvanPlaice porque la versión de Python de varios findscripts que tengo es fea, larga e imposible de mantener en comparación. Muchas cosas deberían ser scripts de shell, muchas otras no . No todo debe ser solo Python o BASH (o cualquier otra cosa).
mikebabcock
8
@mikebabcock Idealmente, habría una biblioteca completa que implemente todas las microherramientas que están disponibles en la pila básica * nix. Se incluirían funciones como find () y last () y, en lugar de tuberías, una combinación de curry y carga perezosa se encargaría de pegar todo junto. ¿No sería bueno tener un entorno de script POSIX que funcione de manera estándar en todas las distribuciones? Nada de eso existe, sin embargo ...
Evan Plaice
2
El punto sobre las tuberías de concha (como (a | b; c ) | something >result) se mitiga de alguna manera porque es trivialmente fácil pasar las tuberías de concha a los subprocessmétodos que usanshell=True
iruvar
103

Sí, por supuesto :)

Eche un vistazo a estas bibliotecas que lo ayudan. Nunca vuelva a escribir scripts de shell (lema de Plumbum).

Además, si desea reemplazar awk, sed y grep con algo basado en Python, le recomiendo pyp :

"The Pyed Piper", o pyp, es una herramienta de manipulación de texto de línea de comandos de Linux similar a awk o sed, pero que utiliza métodos estándar de cadena y lista de Python, así como funciones personalizadas desarrolladas para generar resultados rápidos en un entorno de producción intenso.

Piotr Dobrogost
fuente
También eche un vistazo a Envoy, que es una alternativa a sh github.com/kennethreitz/envoy
AllanLRH
57

Acabo de descubrir cómo combinar las mejores partes de bash e ipython. Hasta ahora, esto me parece más cómodo que usar subprocesos, etc. Puede copiar fácilmente grandes partes de scripts de bash existentes y, por ejemplo, agregar manejo de errores en la forma de python :) Y aquí está mi 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 los documentos de IPython sobre los comandos del shell del sistema y su uso como shell del sistema .

La K
fuente
11
Upvoted porque por alguna extraña razón, nadie más ha mencionado los comandos! En IPython, que son absolutamente clave; especialmente porque también puede asignar su salida a una variable (lista de líneas) como enfilelines = ! cat myfile
kampu
¿Y puede usar las variables de Python como $varen un comando de shell? Guau. Esta debería ser la respuesta aceptada.
Chiel ten Brinke
Y también puede usarlo desde los cuadernos jupyter
Yuval Atzmon,
44

A partir de 2015 y el lanzamiento de Python 3.4, ahora hay un shell interactivo para el usuario razonablemente completo disponible en: http://xon.sh/ o https://github.com/scopatz/xonsh

El video de demostración no muestra las tuberías que se utilizan, pero ESTÁN compatibles cuando se encuentra en el modo de shell predeterminado.

Xonsh ('concha') se esfuerza mucho por emular bash, por lo que ya has ganado memoria muscular, como

env | uniq | sort -r | grep PATH

o

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

seguirá funcionando bien.

El tutorial es bastante extenso y parece cubrir una cantidad significativa de la funcionalidad que alguien esperaría generalmente en un aviso de ceniza o bash:

  • ¡Compila, evalúa y ejecuta!
  • Historial de comandos y finalización de pestañas
  • Ayuda y Superayuda con ?&??
  • Alias ​​y mensajes personalizados
  • Ejecuta comandos y / o *.xshscripts que también se pueden importar
  • Variables de entorno, incluida la búsqueda con ${}
  • Redirección de entrada / salida y combinación
  • Trabajos en segundo plano y control de trabajos
  • Subprocesos de anidamiento, tuberías y coprocesos
  • Modo subproceso cuando existe un comando, modo Python en caso contrario
  • $()Subproceso capturado con , Subproceso no capturado con $[], Evaluación de Python con@()
  • Filename Globbing con *o expresión regular Filename Globbing con Backticks
Kamilion
fuente
Pero, ¿por qué parece que todas estas respuestas solo reinventan la rueda para las personas que no saben bash ? Me he sentido moderadamente cómodo con bash y cada una de estas respuestas parece que terminará siendo más trabajo por poco beneficio. Todas estas respuestas están dirigidas a las personas python que tienen miedo (o no quieren pasar el tiempo aprendiendo) bash, ¿estoy en lo cierto?
Buttle Butkus
Parece que tiene algunas desventajas, como el requisito de usar la .xshextensión para archivos con el código xonsh : github.com/xonsh/xonsh/issues/2478 . De lo contrario, debe usarlo evalxpara llamarlo directamente desde los .pyarchivos.
Andry
31
  • Si desea utilizar Python como shell, ¿por qué no echar un vistazo a IPython ? También es bueno aprender interactivamente el idioma.
  • Si hace mucha manipulación de texto y usa Vim como editor de texto, también puede escribir directamente complementos para Vim en Python. simplemente escriba ": help python" en Vim y siga las instrucciones o eche un vistazo a esta presentación . ¡Es tan fácil y poderoso escribir funciones que usará directamente en su editor!
Mapad
fuente
8
hay un perfil ipython llamada 'sh' que hace que el intérprete muy parecido a una concha.
Autoplectic
3
El perfil 'sh' de ipython se ha eliminado desde hace algún tiempo.
gdw2
>>> resultado =! dmesg | grep -i 'usb' #the! operador lo hace todo
Permafacture
16

Al principio había sh, sed y awk (y find, y grep, y ...). Estuvo bien. Pero awk puede ser una pequeña bestia extraña y difícil de recordar si no la usas con frecuencia. Entonces el gran camello creó a Perl. Perl era el sueño de un administrador de sistemas. Era como una secuencia de comandos de shell en los esteroides. El procesamiento de texto, incluidas las expresiones regulares, eran solo parte del lenguaje. Luego se puso feo ... La gente trató de hacer grandes aplicaciones con Perl. Ahora, no me malinterpreten, Perl puede ser una aplicación, pero puede (¡puede!) Parecer un desastre si no eres realmente cuidadoso. Luego está todo este negocio de datos planos. Es suficiente para volver loco a un programador.

Ingrese Python, Ruby, et al. Estos son realmente muy buenos lenguajes de propósito general. Admiten el procesamiento de texto y lo hacen bien (aunque tal vez no estén tan entrelazados en el núcleo básico del lenguaje). Pero también se amplían muy bien y todavía tienen un código atractivo al final del día. También han desarrollado comunidades bastante fuertes con muchas bibliotecas para casi cualquier cosa.

Ahora, gran parte de la negatividad hacia Perl es una cuestión de opinión, y ciertamente algunas personas pueden escribir Perl muy limpio, pero con esto muchas personas se quejan de que es demasiado fácil crear código ofuscado, sabes que hay algo de verdad allí. La pregunta realmente es, entonces, ¿vas a usar este lenguaje para más que simples reemplazos de script bash? Si no, aprende más Perl ... es absolutamente fantástico para eso. Si, por otro lado, desea un lenguaje que crezca con usted a medida que desea hacer más, puedo sugerir Python o Ruby.

De cualquier manera, ¡buena suerte!

MattG
fuente
9

Sugiero el increíble libro en línea Sumérgete en Python . Así es como aprendí el idioma originalmente.

Más allá de enseñarle la estructura básica del lenguaje y una gran cantidad de estructuras de datos útiles, tiene un buen capítulo sobre el manejo de archivos y capítulos posteriores sobre expresiones regulares y más.

Dan Lenski
fuente
1
... problema principal de las respuestas de solo enlace.
Jean-François Fabre
7

Agregar a respuestas anteriores: verifique el módulo pexpect para tratar con comandos interactivos (adduser, passwd, etc.)

Federico A. Ramponi
fuente
7

Una razón por la que amo Python es porque está mucho mejor estandarizado que las herramientas POSIX. Tengo que verificar doble y triplemente que cada bit sea compatible con otros sistemas operativos. Un programa escrito en un sistema Linux podría no funcionar igual en un sistema BSD de OSX. Con Python, solo tengo que verificar que el sistema de destino tenga una versión suficientemente moderna de Python.

¡Aún mejor, un programa escrito en Python estándar incluso se ejecutará en Windows!

Hal Canary
fuente
1
"un programa escrito en Python estándar incluso se ejecutará en Windows": ¿no es broma?
Jean-François Fabre
6

Daré aquí mi opinión basada en la experiencia:

Para la cáscara:

  • Shell puede generar fácilmente código de solo lectura. Escríbelo y cuando vuelvas a él, nunca descubrirás lo que hiciste nuevamente. Es muy fácil lograr esto.
  • Shell puede hacer MUCHO procesamiento de texto, división, etc. en una línea con tuberías.
  • Es el mejor lenguaje de pegamento cuando se trata de integrar la llamada de programas en diferentes lenguajes de programación.

Para python:

  • si desea portabilidad a Windows incluido, use python.
  • Python puede ser mejor cuando debe manipular algo más que texto, como colecciones de números. Para esto, recomiendo python.

Por lo general, elijo bash para la mayoría de las cosas, pero cuando tengo algo que debe cruzar los límites de Windows, solo uso python.

Germán Diago
fuente
4

pythonpy es una herramienta que proporciona un fácil acceso a muchas de las funciones de awk y sed, pero que utiliza la sintaxis de python:

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

He creado scripts de shell semi largos (300-500 líneas) y código Python que tiene una funcionalidad similar. Cuando se ejecutan muchos comandos externos, creo que el shell es más fácil de usar. Perl también es una buena opción cuando hay mucha manipulación de texto.

Mike Davis
fuente
3

Mientras investigaba este tema, encontré este código de prueba de concepto (a través de un comentario en http://jlebar.com/2010/2/1/Replacing_Bash.html ) que le permite "escribir tuberías similares a shell en Python usando un sintaxis breve y aprovechando las herramientas del sistema existentes donde tienen sentido ":

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

Su mejor apuesta es una herramienta específicamente orientada a su problema. Si está procesando archivos de texto, entonces Sed, Awk y Perl son los principales contendientes. Python es un lenguaje dinámico de propósito general . Al igual que con cualquier lenguaje de propósito general, hay soporte para la manipulación de archivos, pero ese no es su propósito principal. Consideraría Python o Ruby si tuviera un requisito para un lenguaje dinámico en particular.

En resumen, aprende Sed y Awk realmente bien, además de todas las otras golosinas que vienen con tu sabor de * nix (Todos los elementos incorporados de Bash, grep, tr, etc.). Si le interesa el procesamiento de archivos de texto, ya está utilizando las cosas correctas.

Eric Smith
fuente
2

Puede usar python en lugar de bash con la biblioteca ShellPy .

Aquí hay un ejemplo que descarga el avatar del usuario de Python desde 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 puede ver, todas las expresiones dentro del símbolo de acento grave (`) se ejecutan en shell. Y en el código Python, puede capturar los resultados de esta ejecución y realizar acciones en él. Por ejemplo:

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

Esta línea se ejecutará primero git log --pretty=oneline --grep='Create'en shell y luego asignará el resultado a la variable de registro. El resultado tiene las siguientes propiedades:

stdout todo el texto de stdout del proceso ejecutado

stderr todo el texto de stderr del proceso ejecutado

código de retorno código de retorno de la ejecución

Esta es una descripción general de la biblioteca, una descripción más detallada con ejemplos se puede encontrar aquí .

Alexander Ponomarev
fuente
1

Si su manipulación de archivos de texto generalmente es de una sola vez, posiblemente realizada en el indicador de comandos de shell, no obtendrá nada mejor de python.

Por otro lado, si generalmente tiene que hacer la misma tarea (o similar) una y otra vez, y tiene que escribir sus scripts para hacerlo, entonces Python es excelente, y puede crear fácilmente sus propias bibliotecas (puede hacerlo eso con scripts de shell también, pero es más engorroso).

Un ejemplo muy simple para tener un sentimiento.

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

Compruebe también el módulo sys y getopt, son los primeros que necesitará.

Davide
fuente
1

He publicado un paquete en PyPI: ez .
Use pip install ezpara instalarlo.

Ha empaquetado comandos comunes en shell y muy bien mi lib usa básicamente la misma sintaxis que shell. por ejemplo, cp (fuente, destino) puede manejar tanto el archivo como la carpeta. (envoltorio de shutil.copy shutil.copytree y decide cuándo usar cuál). Aún más agradable, puede soportar la vectorización como R!

Otro ejemplo: no os.walk, use fls (path, regex) para buscar archivos recursivamente y filtrarlos con expresión regular y devuelve una lista de archivos con o sin ruta completa

Ejemplo final: puede combinarlos para escribir scripts muy simples:
files = fls('.','py$'); cp(files, myDir)

¡Definitivamente échale un vistazo! ¡Me ha costado cientos de horas escribirlo / mejorarlo!

Jerry T
fuente
1
Parece interesante, pero no puedo romper los documentos sin formato en pypi.python.org/pypi/ez , lo siento ...
Greg Dubicki