【问题标题】:Python process text file with these criteria具有这些条件的 Python 处理文本文件
【发布时间】:2014-05-21 21:11:55
【问题描述】:

我正在尝试使用某些标准清理文本文件。

我的文字是这样显示的

NHIST_0003 (ZS.MC.BGE.0424SPVCOS) (21.12) 14.08
(ZS.MC.BLK.0424SPVCOS) (21.12) 14.08
(ZS.MC.GRY.0424SPVCOS) (21.12) 14.08
(ZS.MC.BLK.0525SPVCOS3) (21.12) 14.08
(ZS.MC.GRY.0525SPVCOS2) (21.12) 14.08
NHIST_0004 (ZS.MC.BGE.0424SPVCOS) (21.12) 14.08

如果该行之前有任何文本,我需要删除第一个“(”括号之前的任何文本,并删除我要保留的文本的括号。我还需要删除带括号的数字里面。看着第一行,我只想保留

ZS.MC.BGE.0424SPVC0S 14.08

这些是我想出的试图把事情联系起来的代码。我宁愿不使用 re 表达式,因为现阶段对我来说太先进了。

fileName='reach.txt'
fileName2='outreach.txt'


while True:
    f=open(fileName,'r')
    for words in f:
        x=words.split('(', 1)[-1]
        g = open(fileName2,'w')
        g.write(x)
        g.close()

这个循环是无限的。我认为通过关闭文件,我是在告诉系统停止处理行。

【问题讨论】:

  • with open(file, 'r') as fh: for row in fh: row[:row.find('(')] 或者只是做row.split() 并拿走你想要的东西。例如x = row.split()x[1], x[3]
  • 但是即使文本文件的格式始终不同,x = row.split() 和 x[1], x[3] 也会起作用吗?
  • 它没有,所以我重新编写了代码以找到(...),然后取出行中的最后一项,因为这似乎是一致的。
  • 尝试了我的最新编辑,结果与您的“我想要这个结果”相符:)

标签: python string io strip


【解决方案1】:

如果每一行都有(code you want) (thing you don't want) 之类的内容,您可以尝试使用正则表达式。

import re
infile = 'reach.txt'
outfile = 'outreach.txt'

with open(infile, 'r') as inf, open(outfile, 'w') as outf:
    for line in inf:
        # each line has "* (what you want) (trash) *"
        # always take first one
        first = re.findall("(\([A-z0-9\.]*\))", line)[0]

        items = line.strip().split(" ")
        second = line[-1]
        to_write = " ".join((first, second))
        outf.write(to_write + "\n")

正则表达式"(\([A-z0-9\.]*\))" 匹配以下任意组合(用[ ]* 表示):

  • 信件(A-z),
  • 数字 (0-9),和
  • 句号(\.

在括号内 (\( \))。

在您的示例中,总会有两个匹配项,例如 ZS.MC.BLK.0424SPVCOS21.12re.findall 将按照给定的顺序找到这两个。因为你想要的总是第一个,所以用re.findall(regex, line)[0]抓住它。

【讨论】:

  • 现在还不能恢复。对我来说太超前了。阅读它我只是没有得到通配符
  • @weemo . 仅表示任何字符。所以'a..' 将匹配任何以'a' 开头的三个字符串。
  • 感谢所有这些..将接受并通读...非常感谢您的反馈
【解决方案2】:
blacklist = set('1234567890.')
with open('reach.txt') as infile, open('outreach.txt', 'w') as outfile:
    for line in infile:
        line = line.strip()
        if not line:
            continue
        _left, line = line.split("(", 1)
        parts = [p.rstrip(")").lstrip("(") for p in line.split()]
        parts = [p for i,p in enumerate(parts) if not all(char in blacklist for char in p) or i==len(parts)-1]
        outfile.write("%s\n" %(' '.join(parts)))

你的例子reach.txt,我明白了

ZS.MC.BGE.0424SPVCOS 14.08
ZS.MC.BLK.0424SPVCOS 14.08
ZS.MC.GRY.0424SPVCOS 14.08
ZS.MC.BLK.0525SPVCOS3 14.08
ZS.MC.GRY.0525SPVCOS2 14.08
ZS.MC.BGE.0424SPVCOS 14.08

【讨论】:

  • ValueError: 需要超过 1 个值才能解压
  • @weemo:显示输入。我怀疑文件末尾有一个空行。如果是这样,编辑应该会有所帮助
  • 无论如何我可以发布整个文本文件吗?是 4,000 行。不幸的是,没有严格遵循格式
  • @weemo:我们需要一个最小的工作示例。因此,要么在您的 OP 中发布一组所有可能的行,要么描述所有可能性,以便提供更强大的解决方案
【解决方案3】:

您可以像这样遍历文件中的行:

with open('filename.txt') as f:
    for line in f.readlines():
        #do stuff

要从您想要的行中获取信息,您可以这样做:

cleaned = []
items = line.split()
for item in items:
    if item.startswith('(') and item.endswith(')'):
        cleaned.append(item.strip('()'))
        break
cleaned.append(items[-1])
cleaned = ' '.join(cleaned)

完整程序:

in_file = 'reach.txt'
out_file = 'outreach.txt'

def clean(string):
    if not string:
        return string

    cleaned = []
    items = string.split()
    for item in items:
        if item.startswith('(') and item.endswith(')'):
            cleaned.append(item.strip('()'))
            break
    cleaned.append(items[-1])
    return ' '.join(cleaned)

with open(in_file) as i, open(out_file, 'w') as o:
    o.write('\n'.join([clean(line) for line in i]))

【讨论】:

  • 或只是for line in f,同样的事情。由于缺少:,这也会导致语法错误(已为您修复)
  • 太棒了!!非常感谢。我喜欢你写它的方式。非常易读和简单。
  • Scorpion_God 喜欢该代码,但提示超出索引错误
  • 上面写着第 16 行和第 11 行
  • @weemo 那么你的文本文件中也有空行吗?它现在适用于空行。
【解决方案4】:
fileName='reach.txt'
fileName2='outreach.txt'

def isfloat(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

g = open(fileName2, 'w')
with open(fileName, 'r') as fh:
    for row in fh:
        x = row.split()
        for item in x:
            if '(' in item and ')' in item:
                first = item.strip('()')
                break
        for i in range(-1, 0-len(x), -1):
            second = x[i]
            if isfloat(second):
                break
        print(first, second)
        g.write(' '.join((first, second)) + '\n')
g.close()

这给出了:

ZS.MC.BGE.0424SPVCOS 14.08
ZS.MC.BLK.0424SPVCOS 14.08
ZS.MC.GRY.0424SPVCOS 14.08
ZS.MC.BLK.0525SPVCOS3 14.08
ZS.MC.GRY.0525SPVCOS2 14.08
ZS.MC.BGE.0424SPVCOS 14.08

好了,这段代码将处理数据中的各种错误。 例如,如果浮动值不在将被覆盖的最后,如果(...) 数据未固定在第二个位置而是第一个位置,则也将被覆盖。

【讨论】:

    猜你喜欢
    • 2010-11-29
    • 2014-03-06
    • 2017-06-18
    • 2020-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-02
    • 1970-01-01
    相关资源
    最近更新 更多