2012-10-03 26 views
9

Gibt es eine Möglichkeit, ohne eine Doppelschleife zu erreichen, was die folgende Sed Befehl führtPython entspricht Sed

Input:

Time 
Banana 
spinach 
turkey 

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

Output:

Time 
BananaToothpaste 
spinach 
turkey 

Was ich bisher habe, ist eine Doppelliste, die lange dauern würde durch beide.

Liste weist eine Reihe von Zahlen Liste b a die gleiche Reihe von Zahlen, aber in einer anderen Reihenfolge

Für jeden Eintrag in A hat mag ich die Linie in B mit der gleichen Zahl zu finden und einen Mehrwert C bis zum Ende davon.

Hoffe das macht Sinn, auch wenn mein Beispiel nicht.

ich in Bash folgend tat, und es funktioniert aber es war super langsam ...

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 

Dank!

+3

Ihr sed Beispiel ist nicht gleichwertig ersetzen, was Sie versuchen tatsächlich zu machen. –

+0

Also in bash habe ich das gemacht und es hat funktioniert, aber super langsam ... – user1601716

+0

Sie können tatsächlich sed in Python mit dem 'subprocess' Befehl ausführen. – karthikr

Antwort

9

Mit re.sub():

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

Dies fängt eine Gruppe (zwischen den ersten Klammern), und ersetzt sie durch sich selbst (die \ Nummernteil), gefolgt von einem gewünschten Suffix. Es wird benötigt, um r'' (rohe Zeichenfolge) zu verwenden, damit das Escape korrekt interpretiert wird.

0

Es ist möglich, dies mit tmp-Datei mit geringen Systemanforderungen zu tun und nur eine Iteration ohne gesamte Datei in den Speicher zu kopieren:

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

Wenn Sie Python3 das folgende Modul verwenden werden Ihnen helfen: https://github.com/mahmoudadel2/pysed

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

Legen Sie das Modul-Datei in Ihre Python3 Module Pfad, dann:

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

Sie können tatsächlich sed von Python aufrufen. Viele Möglichkeiten, dies zu tun, aber ich verwende gerne das SH-Modul. (yum -y install python-sh)

Die Ausgabe meines Beispielprogramms folgt.

[[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]$ 

Hier ist test_sh.py

import sh 

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

Dies wird wahrscheinlich nur unter Linux.

3

Ein Nachzügler auf das Rennen ist, hier meine Implementierung in Python sed:

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) 

Beispiele:

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

werden alle 'foo' mit 'bar' in foo.txt ersetzen

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

werden alle 'foo' mit 'bar' in 'foo.txt' ersetzen und das Ergebnis in "foo.updated.txt" speichern.

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

wird nur das erste Vorkommen von ‚foo‘ mit ‚bar‘ und speichern Sie das Ergebnis in der ursprünglichen Datei ‚foo.txt‘ zu