【问题标题】:Replace indexed strings in a list and write out to a text file替换列表中的索引字符串并写入文本文件
【发布时间】:2019-10-22 15:29:13
【问题描述】:

我正在尝试替换文本文件中的某些单词(基本上是每行的第二个单词),然后将它们写回新文件或覆盖现有文件。

我以为我正在取得进展,但是当我去写入一个新文件时,我收到一条错误消息,说我无法将列表写入文本文件。我不能简单地将一个单词替换为另一个单词,因为我有一个“else”子句,它涵盖了与我需要替换的其他单词不匹配的任何单词。

这是我尝试修改的文本示例,该文本包含在 .txt 文件中:

id int,
organization_id int,
billing_month date,
fee_type varchar(100),
rate float,
price float,
uom varchar(25),
amount float,
currency_code_id float,
process_ts timestamptz NOT NULL DEFAULT (now())::timestamptz(6)

我想改变:

'int' --> 'BIGINT'
'numeric' --> 'DOUBLE'
'float' --> 'DOUBLE'
ELSE other data type --> 'STRING' .  

在原始数据中,请注意有些还有其他字符,例如“varchar(100)” - 我想用“STRING”替换这些字符并删除“(100)”部分。

然后覆盖或创建一个新的文本文件。因此,如果正确替换,上述示例输出将是:

id BIGINT,
organization_id BIGINT,
billing_month STRING,
fee_type STRING,
rate DOUBLE,
price DOUBLE,
uom STRING,
amount DOUBLE,
currency_code_id DOUBLE,
process_ts STRING

我不知道是否应该创建列表,然后修改它们,然后将这些列表写入文本文件、字典或其他我没有想到的方法。我是一个初学者,如果这不是很清楚,请道歉。

【问题讨论】:

  • 解决方案是否需要在python中? Perl 也可以做到这一点。它更适合字符串替换。
  • 是的,不幸的是,我 100% 不熟悉 Perl,所以如果这在 Python 中是可能的,我想坚持下去
  • 我刚刚也将“process_ts”添加到要替换的字符串列表中,因为这是我需要考虑的另一个极端情况。如果重要的话,并不是我所有的字符串行都只有 2 个字长

标签: python python-3.x indexing readlines


【解决方案1】:

txt.txt 的内容:

id int,
organization_id int,
billing_month date,
fee_type varchar(100),
rate float,
price float,
uom varchar(25),
amount float,
currency_code_id float,
process_ts timestamptz NOT NULL DEFAULT (now())::timestamptz(6)

代码:

with open('txt.txt', 'r') as f:
    text = f.read().splitlines()

mapping = {'int':'BIGINT',
           'numeric':'DOUBLE',
           'float':'DOUBLE'}

replaced_text = []
for line in text:
    # temporarily remove comma
    line = line.rstrip(',')
    split_line = line.split()
    other_text, dtype = split_line[0], split_line[1:]
    new_dtype = mapping.get(' '.join(dtype), 'STRING')
    new_line = '{} {},\n'.format(other_text, new_dtype)
    replaced_text.append(new_line)


with open('txt_replaced.txt', 'w') as f:
    f.writelines(replaced_text)

txt_replaced.txt 的内容:

id BIGINT,
organization_id BIGINT,
billing_month STRING,
fee_type STRING,
rate DOUBLE,
price DOUBLE,
uom STRING,
amount DOUBLE,
currency_code_id DOUBLE,
process_ts STRING,

【讨论】:

  • 谢谢,我刚刚编辑了我的原始帖子,将“process_ts timestamptz NOT NULL DEFAULT (now())::timestamptz(6)”作为我需要编辑的一行。知道某些字符串的长度超过 2 个字符串,这是否会改变您的解决方案?事实上,并非我需要编辑的所有行都是 2 个字符串,这给我带来了最大的麻烦
  • 感谢您的帮助 - 我仍然遇到“process_ts”部分的问题,我需要阅读:“process_ts STRING”,中间没有所有其他内容(这些内容: "timestamptz NOT NULL DEFAULT (now())::timestamptz(6)") - 有没有办法消除它?
  • 我明白了,所以字段名称总是一个没有空格的字符串,但数据类型可能有任意数量的空格?
  • @phenderbender 我已经更新了处理边缘情况的代码
  • 非常感谢,确认这看起来按预期工作。我对 new_dtype 能够处理“映射”字典中未包含的数据类型背后的逻辑有点迷茫。有没有一种简单的方法可以向像我这样的菜鸟解释这件作品?
【解决方案2】:

您可以遍历每一行并使用字典替换每行第二个位置的值。这适用于任何长度的行,只要要替换的文本是第二个单词。

#vals to replace
replace_vals = {'int':'BIGINT', 'numeric':'DOUBLE', 'float':'DOUBLE'}

#file we write to
with open('out.txt', 'w') as outfile:
  #file we read from
  with open ("in.txt", 'r') as infile:
    #check each line
    for line in infile:
      #split line into words
      words = line.split()
      #get the first word and then replace the second word, defaulting to STRING
      w = words[0] + " " + replace_vals.get(words[1], 'STRING')
      #add a final newline
      w += "\n"
      #print to file
      outfile.write(w)

Demo

【讨论】:

  • 感谢您的回复,但不幸的是,在此示例中,要替换的单词并不总是第二个单词(尤其是 process_ts 片段)。
  • 您的意思是要替换的单词可能出现在例如位置 3,还是说如果有两个以上的单词,则替换它们all?即我会得到some var int
  • 对于情况(例如:“process_ts timestamptz NOT NULL DEFAULT (now())::timestamptz(6)”第二个字会让我知道我需要用什么替换它,然后我不仅需要替换第二个单词,还需要替换第二个单词之后的任何尾随文本。因此,“process_ts timestamptz NOT NULL DEFAULT (now())::timestamptz(6)”需要在“process_ts STRING”之后正在转换
  • 很高兴为您提供帮助 - 如果它解决了您的问题,请考虑投票并接受答案。
  • 赞成,但由于我是该网站的新手,因此我仍然低于计数的阈值。希望这仍然有帮助!
【解决方案3】:

也许这样的事情可以帮助你:

import os, sys
from re import match as regexSearch

path = os.path.dirname(__file__)
myFile = open(os.path.join(path, "filename.txt"), "r")

regExpr = r"[\w_]+ ([\w\(\)\d:]+)(,|\s)"


with open(os.path.join(path, "newFile.txt"), "w") as f:
    for line in myFile.readlines():
        match = regexSearch(regExpr, line)
        if match:
            result = match.group(1)
            if "int" in result:
                f.write(line.replace(result, "BIGINT"))
            elif result in ["numeric", "float"]:
                f.write(line.replace(result, "DOUBLE"))
            else:
                f.write(line.replace(result, "STRING"))
        else:
            print("couldn't find something in line:\n", line)
    f.close()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-01
    • 2018-04-27
    • 2019-10-09
    • 2015-01-23
    • 1970-01-01
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    相关资源
    最近更新 更多