python: ค้นหาและแทนที่แบบง่าย

Topic: 
 

ที่มาจริง ๆ แล้ว ต้องการค้นหาและแทนที่เอกสารในไฟล์ .doc จึงสั่งด้วยคำสั่งว่า
$ sed -i 's/OLD/NEW/g' *.doc
ไม่ได้ผล นึกว่ารหัสเอกสารผิด เลยเป็นที่มาของสคริปต์อันนี้ คือค้นหาและแทนที่เอกสารทั้ง utf-8 และ tis-620 โดยไม่สนใจว่าเป็นเอกสารชนิดใด
(สุดท้ายปรากฎว่าไม่ได้ผล เพราะ OpenOffice ไม่ได้เก็บไว้ในรูป Text file ปกติ
ถึงจะโง่ไปแล้ว แต่บันทึกไว้หน่อยดีกว่า เผื่อได้ใช้ทีหลัง)

$ vi sed_i.py

#!/usr/bin/env python
# -*- coding: utf8 -*-
"""Replace thai string in file"""

import sys, os

def usage(prog):
    print 'Usage: %s "old" "new" filename' % (prog)

def cannotopenfile(filename):
    print "Cannot open file %s" % (filename)

def getbakfilename(filename="", ext="bak"):
    if filename == "":
        return ""
    if os.path.exists(filename + "." + ext):
        i = 0
        while os.path.exists(filename + "." + ext + str(i)) and (i < 1000):
            i += 1
        if i > 999:
            return ""
        return filename + "." + ext + str(i)
    else:
        return filename + "." + ext
    #

def main(old,new,filename):
    if not os.path.exists(filename):
        cannotopenfile(filename)
        sys.exit(0)
    ismod = False
    newdoc = []
    f = open(filename)
    for line in f:
        newline1 = line.replace(old, new)
        newline2 = line.replace(old.decode('utf8').encode('tis620'), new.decode('utf8').encode('tis620'))
        if not ismod and (newline1 != line or newline2 != line):
            ismod = True
        if newline1 != line:
            newdoc.append(newline1)
        else:
            newdoc.append(newline2)
    f.close()
    if ismod:
        bakfile = getbakfilename(filename)
        os.rename(filename, bakfile)
        f = open(filename, "w")
        f.write('\n'.join(newdoc))
        f.close()
        print "%s changed, save backup in %s." % (filename, bakfile)
    else:
        print "Pattern not found, no changed."


if __name__ == "__main__":
    if len(sys.argv) < 4:
        usage(sys.argv[0])
        sys.exit[0]
    else:
        main(*sys.argv[1:4])

ใช้งานด้วยคำสั่ง
$ ./sed_i.py "OLD" "NEW" filename
ถ้าเจอ จะแทนที่ และบันทึกไว้ในชื่อเดิม แต่สำรองไฟล์ไว้ด้วย ในชื่อ filename.bak