2012-10-03 24 views
9

¿Hay una manera, sin un bucle doble para llevar a cabo lo que el siguiente comando sedpitón equivalente a sed

de entrada:

Time 
Banana 
spinach 
turkey 

sed -i "/Banana/ s/$/Toothpaste/" file

Salida:

Time 
BananaToothpaste 
spinach 
turkey 

Lo que tengo hasta ahora es una lista doble que tomaría mucho tiempo para ir a través de ambos.

Lista a tiene un montón de números Lista B tiene un mismo montón de números, pero en un orden diferente

Para cada entrada en un quiero buscar la línea B con el mismo número y agregar valor C hasta el final.

Espero que esto tenga sentido, incluso si mi ejemplo no lo hace.

que estaba haciendo lo siguiente en Bash y que estaba trabajando sin embargo, era muy lento ...

for line in $(cat DATSRCLN.txt.utf8); do 
     srch=$(echo $line | awk -F'^' '{print $1}'); 
     rep=$(echo $line | awk -F'^' '{print $2}'); 
     sed -i "/$(echo $srch)/ s/$/^$(echo $rep)/" tmp.1; 
done 

Gracias!

+3

Su ejemplo sed no es equivalente a lo que en realidad está tratando de hacer. –

+0

Así que en Bash estaba haciendo esto y estaba funcionando, pero súper lento ... – user1601716

+0

puedes ejecutar sed en python usando el comando 'subprocess'. – karthikr

Respuesta

9

Usando re.sub():

newstring = re.sub('(Banana)', r'\1Toothpaste', oldstring) 

Esto llama un grupo (entre primeros paréntesis), y la reemplaza por sí mismo (la parte \ número) seguido de un sufijo deseado. Es necesario usar r'' (cadena sin procesar) para que el escape se interprete correctamente.

0

Es posible hacer este archivo tmp usando con bajos requerimientos de sistema y sólo una iteración sin copiar todo el archivo en la memoria:

#/usr/bin/python 
import tempfile 
import shutil 
import os 

newfile = tempfile.mkdtemp() 
oldfile = 'stack.txt' 

f = open(oldfile) 
n = open(newfile,'w') 

for i in f: 
     if i.find('Banana') == -1: 
       n.write(i) 
       continue 

     # Last row 
     if i.find('\n') == -1: 
       i += 'ToothPaste' 
     else: 
       i = i.rstrip('\n') 
       i += 'ToothPaste\n' 

     n.write(i) 

f.close() 
n.close() 

os.remove(oldfile) 
shutil.move(newfile,oldfile) 
2

Si está utilizando python3 el siguiente módulo le ayudará a: https://github.com/mahmoudadel2/pysed

wget https://raw.githubusercontent.com/mahmoudadel2/pysed/master/pysed.py 

Coloque el archivo de módulo en su python3 módulos de vía, entonces:

import pysed 
pysed.replace(<Old string>, <Replacement String>, <Text File>) 
pysed.rmlinematch(<Unwanted string>, <Text File>) 
pysed.rmlinenumber(<Unwanted Line Number>, <Text File>) 
1

Puedes llamar a sed desde python. Muchas formas de hacerlo, pero me gusta usar el módulo sh. (yum -y install python-sh)

La salida de mi programa de ejemplo es la siguiente.

[[email protected] sh]$ cat input 
Time 
Banana 
spinich 
turkey 
[[email protected] sh]$ python test_sh.py 
[[email protected] sh]$ cat input 
Time 
Toothpaste 
spinich 
turkey 
[[email protected] sh]$ 

Aquí es test_sh.py

import sh 

sh.sed('-i', 's/Banana/Toothpaste/', 'input') 

Esto probablemente sólo funcionan en Linux.

3

Un recién llegado a la carrera, aquí está mi aplicación para la sed en Python:

import re 
import shutil 
from tempfile import mkstemp 


def sed(pattern, replace, source, dest=None, count=0): 
    """Reads a source file and writes the destination file. 

    In each line, replaces pattern with replace. 

    Args: 
     pattern (str): pattern to match (can be re.pattern) 
     replace (str): replacement str 
     source (str): input filename 
     count (int): number of occurrences to replace 
     dest (str): destination filename, if not given, source will be over written.   
    """ 

    fin = open(source, 'r') 
    num_replaced = count 

    if dest: 
     fout = open(dest, 'w') 
    else: 
     fd, name = mkstemp() 
     fout = open(name, 'w') 

    for line in fin: 
     out = re.sub(pattern, replace, line) 
     fout.write(out) 

     if out != line: 
      num_replaced += 1 
     if count and num_replaced > count: 
      break 
    try: 
     fout.writelines(fin.readlines()) 
    except Exception as E: 
     raise E 

    fin.close() 
    fout.close() 

    if not dest: 
     shutil.move(name, source) 

ejemplos:

sed('foo', 'bar', "foo.txt") 

reemplazará todos 'foo' con 'bar' en foo.txt

sed('foo', 'bar', "foo.txt", "foo.updated.txt") 

sustituirá a todos 'foo' con 'barra' en 'foo.txt' y guardar el resultado en "foo.updated.txt".

sed('foo', 'bar', "foo.txt", count=1) 

reemplazará sólo la primera aparición de 'foo' con 'bar' y guardar el resultado en el archivo original 'foo.txt'