简体   繁体   中英

a program to replace a line in a .yml file(PYTHON)

I'm trying to make a tool that will replace a single line in a .yml file(opens as a text document). I have it writing to the file, but it takes everything out and writes the "fixed" line. My code is below, along with a sample of one instance/file. The file names are IMPORTANT and can not change.

import sys
from os import listdir

from os.path import isfile, join
onlyfiles = [ f for f in listdir() if isfile(f) and str(f)[-4:]==".yml" ] #Gets the file names, can be ANYTHING
for pos in range(1, len(onlyfiles)): #So it stops at the end of the List
    with open(onlyfiles[pos], 'r') as a: #Lets open it make sure it is good
        for line in a:
            if line == "  world: Trolling\n": # this is the target line to replace
                line = line.replace("  world: Trolling", "  world: world\n") #rework the line, though it wont write even if i change the R to W
                with open(onlyfiles[pos], 'w') as repl: #Writes to the file, but gets rid of everything else
                    repl.write(line)
                    print(line)

Sample of un-modified document:

timestamps:
  login: 1373913158118
  lastteleport: 1373918169442
  logout: 1373918539235
  kits:
    trusted: 1373052268213
ipAddress: 142.165.45.129
nickname: Erin
lastlocation:
  world: Trolling
  x: -890.6999999880791
  y: 87.0
  z: -764.6999999880791
  yaw: 91.99242
  pitch: 75.449974
homes:
  e:
    world: Trolling
    x: 4653.2140183238
    y: 64.0
    z: 80.02726116652944
    yaw: 192.08363
    pitch: 66.29998

I'm trying to replace instances of "Trolling" with "world", across 100+ files, without touching anything else

You need an else condition after if line == " world: Trolling\\n" for when the line does not match this pattern. Also put all the data you're writing back into some variable and write that in one shot at the end after closing the file you're reading from, you cannot read and write to a file at the same time.

import sys
from os import listdir 
from os.path import isfile, join

onlyfiles = [ f for f in listdir() if isfile(f) and str(f)[-4:]==".yml" ]

for file in onlyfiles:
  wdata = ''
  with open(file, 'r') as a: #Lets open it make sure it is good
    for line in a: 
        if line == "  world: Trolling\n":
            line = "  world: world\n" # You already know what it should be
        print line
        wdata += line
  with open(file, 'w') as repl: 
    repl.write(wdata)

It's probably easier to just do

for file in onlyfiles:
  with open(file, 'r') as f:
    d = f.read().replace('\n  world: Trolling\n','\n  world: world\n')
  with open(file, 'w') as f:
    f.write(d)

I would probably go for a more general solution.

import yaml

def replace(doc, inval, outval):
    if isinstance(doc, dict):
        for k, v in doc.items():
            if v == inval:
                doc[k] = outval
            elif isinstance(v, dict):
                doc[k] = replace(v, inval, outval)
            elif isinstance(v, list):
                for i, item in enumerate(v[:]):
                    doc[k][i] = replace(item, inval, outval)
    return doc


doc = yaml.load(open("original.yml"))
newdoc = replace(doc, "Trolling", "world")
yaml.dump(newdoc, open("modified.yml", "w"))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM