【问题标题】:Replace specific string in file in Python在Python中替换文件中的特定字符串
【发布时间】:2019-03-02 17:18:44
【问题描述】:

首先,因为我以前被人用过电源绊倒,所以这个问题不适合做作业。

无论如何,我有一个类似于以下内容的文本文件:

####
# File section 1
####

1.0   abc   Description1
6.5   def   Description2
1.0 2.0 3.0   ghi   Description3
11    jkl   Description

####
# File section 2
####

1.0   abc   Description1
12.5   def   Description2
1.0 2.0 3.0   ghi   Description3
11    jkl   Description

#### End file

我想替换两行中的字符串“1.0”:

1.0   abc   Description1

但是,不是行中的“1.0”字符串:

1.0 2.0 3.0   ghi   Description3

我当前使用的代码是:

with open('sample_file.txt','r') as file:
    filedata = file.read()
    filedata = filedata.replace('1.0','2.0')
with open('sample_file.txt','w') as file:
    file.write(filedata)

但是结果是所有出现的“1.0”都被替换了。然后我必须回到文件中,并纠正错误。我想得到的结果文件是:

####
# File section 1
####

2.0   abc   Description1
6.5   def   Description2
1.0 2.0 3.0   ghi   Description3
11    jkl   Description

####
# File section 2
####

2.0   abc   Description1
12.5   def   Description2
1.0 2.0 3.0   ghi   Description3
11    jkl   Description

#### End file

我怎样才能得到它?我找不到此类问题的示例解决方案。谢谢大家的帮助。

编辑:我的错没有澄清,但我要替换的字符串并不总是“1.0”,也不总是 3 个字符长。例如,它可以是“-12.3”。我想让代码尽可能通用。

我还尝试使用 rsplit 以空格作为分隔符来隔离第一个字符串,但这似乎不适用于文件写入。

==========================

EDIT2:我找到了一种方法来做到这一点,虽然它似乎是一个相当迂回的方法:

with open('sample_file.txt','r') as file:
    filedata = file.readlines()
        for line in filedata:
            if 'abc' in line:
                oriline = line
                newline = line.replace(str(spk),str(newspk))
with open('sample_file.txt','r') as file:
    filedata = file.read()
    filedata = filedata.replace(str(oriline),str(newline))
with open('sample_file.txt','w') as file:
    file.write(filedata)

基本上,它会打开文件,逐行读取包含我想要的特定字符串的整行,然后将其存储到内存中。然后再次打开文件,读取所有内容,然后替换整个字符串。然后打开文件,写入文件。

它做了我想要的,但是有没有办法简化代码?

【问题讨论】:

  • 使用regular expressions 查找您想要的字符串模式并对该模式的一部分执行替换。如果不确切知道您要替换的内容的标准是什么,我们很难给您一个更具体的答案(即,您是否只想为标记为“abc”的条目替换“1.0”?您想替换“1.0”吗? " 仅当同一行没有其他数字时?)
  • 我只想将行中的“1.0”字符串替换为“abc”,因为“abc”是我正在使用的代码中的一个变量。
  • 关于 EDIT2:没有理由读取文件两次。您可以就地修改filedata 的元素,然后在filedata 上使用file.writelines。此外,只有一个oriline,因此如果“abc”在同一个文件中出现两次(如您的示例中),它将不起作用。此外,如果“abc”出现在行中anywhere(包括描述),您将执行替换并将spk所有 出现替换为newspk(无论那些是),而不仅仅是在第一个令牌中。您还声明要替换的字符串不是固定字符串,您的方法无法处理。
  • 我建议的两种方法有什么问题?他们应该处理您所说的要求。如果它们不合适,请说明原因。

标签: python file replace io


【解决方案1】:

随便用

with open('sample_file.txt','r') as file:
    filedata = file.read()
    filedata = filedata.replace('1.0   abc','2.0   abc')
with open('sample_file.txt','w') as file:
    file.write(filedata)

除了上面的快捷方式,你可以先定义一个空列表来尝试更通用的情况:

li = []

然后使用下面的代码(考虑到字符串abc 在上述情况下是固定的):

with open('sample_file.txt','r') as file:
for line in file:
        i = line.find('abc',1)
        if i >= 0:
              lineval = line.replace('1.0','2.0')
              li.append(lineval)
        else:
              lineval = line
              li.append(lineval)
j = 0                 
with open('sample_file.txt','w') as file:
    while j < len(li):
        file.write(li[j])           
        j += 1

【讨论】:

  • 我的错没有澄清,但我要替换的字符串并不总是“1.0”,也不总是3个字符长。例如,它可以是“-12.3”。我想让代码尽可能通用。
  • 这对于 OP 的情况可能已经足够了,但请注意,如果“abc”出现在任何地方,第二个代码示例将替换 所有 出现的“1.0” 就行了。
  • @jamesdlin 当然,我故意这样做取决于他样本中的关键字。无论如何,谢谢。
  • 在你们的启发下,我尝试了自己的方法(编辑 2),它似乎奏效了。你们能否对我可以改进代码的方法提出一些批评?
【解决方案2】:

正如我在评论中提到的,您可以使用regular expressions 来匹配您正在寻找的模式。您可以在模式中指定(使用(...)(?P&lt;name...))来识别模式的各个部分并专门更换或重复使用这些部件。

这样的事情应该可以工作:

import re

pattern = (r'^' # The beginning of a line.
           # Match something that looks like a number:
           r'-?'        # 1. Optional: a negative sign.
           r'\d+'       # 2. One or more digits.
           r'([.]\d+)?' # 3. Optional: a decimal point followed by one
                        #    or more digits.
           # The rest of the line:
           r'(?P<rest>'
             r'\s+' # 1. One or more spaces.
             r'abc' # 2. "abc"
             r'\s+' # 3. One or more spaces.
             r'.*'  # 4. Everything remaining.
           r')' 
           r'$') # The end of a line.

# Replace the above pattern with "2.0" followed by whatever we identified
# as "the rest of the line".
replacement = '2.0\g<rest>'

with open('sample_file.txt','r') as file:
    filedata = file.read()

    # re.MULTILINE is needed to treat lines separately.
    filedata = re.sub(pattern, replacement, filedata, flags=re.MULTILINE)
with open('sample_file.txt','w') as file:
    file.write(filedata)

不使用正则表达式的不同(未经测试)方法:

with open('sample_file.txt','r') as file:
    lines = file.readlines()

with open('sample_file.txt','w') as file:
    for line in lines:
        tokens = line.split(maxsplit=2)
        try:
            if float(tokens[0]) and tokens[1] == 'abc':
                tokens[0] = '2.0'
        except (IndexError, ValueError):
            pass
        else:
            line = ' '.join(tokens)
        file.write(line)

请注意,这与正则表达式 (RE) 方法并不完全相同(显着的区别在于它将接受任何浮点数作为第一个标记(例如 1e-10)并且不会保留执行替换后的空格),但如果您不熟悉 RE,可能会更容易理解。

【讨论】:

    猜你喜欢
    • 2020-03-06
    • 2017-05-03
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    • 1970-01-01
    • 2014-06-21
    • 1970-01-01
    • 2012-09-14
    相关资源
    最近更新 更多