2008-12-14 9 views
15

Sé de python -c '<code>', pero me pregunto si hay una python más elegante equivalente a perl -pi -e '<code>'. Todavía lo uso bastante para cosas como buscar y reemplazar en un directorio completo (perl -pi -e s/foo/bar/g * o incluso find . | xargs perl -pi -e s/foo/bar/g para subdirectorios).¿Hay un Python equivalente a `perl -pi -e`?

De hecho, creo que lo que hace Perl Perl (forma gratuita Tim Toady-ness) es lo que hace que perl -pi -e funcione tan bien, mientras que con Python tendrías que hacer algo similar a la importación del módulo re, creando un re instancia y luego capturar la entrada estándar, pero tal vez hay un acceso directo Python que hace todo eso y no me di cuenta (echa en falta a ella) ...

+2

Francamente, suena como algo que Guido no aprobaría. – Axeman

+0

Seguramente quieres decir encontrar. -type f | xargs perl ...? –

+0

Puedes usar Ruby en su lugar. En Ruby, el equivalente de 'perl -pi -e' es' ruby ​​-pi -e'. Haga clic en [este enlace] (http://stackoverflow.com/questions/1274605/ruby-search-file-text-for-a-pattern-and-replace-it-with-a-given-value#3502884) para más información información. – unforgettableid

Respuesta

9

El uso de la línea de comandos de 'python -h' ciertamente sugiere fuertemente que no hay tal equivalente. Perl tiende a hacer un uso extensivo de '$_' (sus ejemplos hacen un uso implícito de él), y no creo que Python admita ningún concepto similar, lo que hace que los equivalentes de Python de los lineamientos de Perl sean mucho más difíciles.

24

Python es para los muggles. Si quieres magia, ¡Perl deberías usarla!

10

Un equivalente a -pi no es tan difícil de escribir en Python.

  1. Escriba usted mismo un práctico módulo con las características -p y -i que realmente le gustan. Vamos a llamarlo pypi.py.

  2. Uso python -c 'import pypi; pypi.subs("this","that")'

se puede implementar el bucle básico -p con el módulo fileinput.

Tendría una función, subs que implementa el algoritmo esencial "-i" de abrir un archivo, guardar la copia de seguridad y hacer el sustituto en cada línea.

Existen algunas recetas de ActiveState como esta. Éstos son algunos:

no incorporado. Pero no es difícil de escribir. Y una vez escrito fácil de personalizar.

+3

Sugeriría que el módulo se llame pi.py, se almacene dentro del directorio site-packages, termine con una construcción 'if __name__ ==" __main __ ":', y luego se invoque con 'python -mpi ... ' – tzot

6

Creo que Perl es más adecuado para este tipo de scripting sobre la marcha. Si desea una capacidad de creación de guiones única sobre la marcha, le recomiendo que se adhiera a las herramientas de línea de comandos de Perl, Awk, Sed y Unix estándar.

Pero si está interesado en usar python, uso optparse para escribir mis propias herramientas de línea de comandos y recomendarlo. optparse proporciona un analizador de opciones de línea de comandos limpio y fácil de usar con generación de ayuda incorporada.

He aquí una muestra:

def myfunc(filename, use_versbose): 
    # function code 

if __name__ == '__main__': 
    from optparse import OptionParser 

    parser = OptionParser() 
    parser.add_option("-f", "--file", dest="filename", 
         help="write report to FILE", metavar="FILE") 
    parser.add_option("-q", "--quiet", 
         action="store_false", dest="verbose", default=True, 
         help="don't print status messages to stdout") 

    (options, args) = parser.parse_args() 

    if options.filename: 
     myfunc(options.filename, options.verbose) 

    else: 
     print 'ERROR -- Necessary command line options not given!' 
     print parser.print_help() 

analizador.print_help() genera la siguiente salida, y se visualiza automáticamente cuando -h o --help se da en la línea de comando:

usage: <yourscript> [options] 

options: 
    -h, --help   show this help message and exit 
    -f FILE, --file=FILE write report to FILE 
    -q, --quiet   don't print status messages to stdout 
+3

Esto de ninguna manera es un reemplazo para un trazador de líneas, y por lo tanto la mayor parte de esto no es una respuesta a la pregunta –

+3

Sí, pero quizás la solución más elegante no es equivalente a' perl -pi-e ' , pero escribiendo sus propias herramientas de línea de comandos para las tareas que se realizan con frecuencia. "myscript.py -x this -y that" puede estar más limpio que "python -c 'import this; dostuff (this, that)'". Depende de tus necesidades y preferencias individuales. – monkut

2

El módulo fileinput tiene la capacidad para la edición in situ. Sin embargo, no puede prescindir de las copias de seguridad. Aquí es cómo usarlo para una sola línea:

python -c 'import fileinput, sys; for line in fileinput.input(inplace=True): sys.stdout.write(line, "foo", "bar")' 

Personalmente, acabo de suelo usar Perl cuando tengo que hacer algo como esto. Es una de las pocas veces que uso Perl.

9

Sé que esto es un par de años demasiado tarde, pero recientemente he encontró una muy buena herramienta llamada pyp, que hace exactamente lo lo solicitado.

creo que el comando debe ser:

pyp "p.replace('foo','bar')" 
+1

¡Bonito hallazgo! pyp ("The Pyed Piper, Piping Python Through Pipes"), de Sony Pictures Imageworks, es muy conciso, flexible, puede hacer estadísticas, canalizaciones internas, etc. Fue presentado en PYCON 2012 "The Pyed Piper: A Modern Python Alternativa a awk, sed y otras utilidades de manipulación de texto de Unix por Toby Rosen " – nealmcb

0

Lo anterior puede funcionar para la entrada estándar, pero no se ve como que trabajaría para un archivo.

Tal vez algo como:

-

import fileinput 
import sys 
for line in fileinput.input("./poop", inplace=True): 
    line = line.replace("foo", "bar") 
    sys.stdout.write(line) 

- donde "./poop" puede ser reemplazado con el lugar donde está el archivo y line.replace debe apoyar cosas como line.replace ("{}". format (variablehere), "newtext")

Cuestiones relacionadas