11

我有一个 .txt 文件(从网站上抓取为预先格式化的文本),其中的数据如下所示:

B, NICKOLAS                       CT144531X       D1026    JUDGE ANNIE WHITE JOHNSON  
ANDREWS VS BALL                   JA-15-0050      D0015    JUDGE EDWARD A ROBERTS        

我想删除列之间的所有额外空格(它们实际上是不同数量的空格,而不是制表符)。然后我还想用一些分隔符(制表符或管道,因为数据中有逗号)替换它,如下所示:

ANDREWS VS BALL|JA-15-0050|D0015|JUDGE EDWARD A ROBERTS

环顾四周,发现最好的选择是使用 regex 或 shlex 进行拆分。两个类似的场景:

4

6 回答 6

7

那这个呢?

your_string ='ANDREWS VS BALL                   JA-15-0050      D0015    JUDGE EDWARD A ROBERTS'
print re.sub(r'\s{2,}','|',your_string.strip())

输出:

ANDREWS VS BALL|JA-15-0050|D0015|JUDGE EDWARD A ROBERTS

扩展:

我使用re.sub()了 3 个参数、一个模式、一个要替换的字符串以及要处理的字符串。

我所做的是至少占用两个空间,我已经用 a 替换了它们|并将它应用到你的字符串上。

于 2016-04-30T17:32:52.413 回答
7

您可以将正则表达式'\s{2,}'(两个或多个空白字符)应用于每一行,并用单个'|'字符替换匹配项。

>>> import re
>>> line = 'ANDREWS VS BALL                   JA-15-0050      D0015    JUDGE EDWARD A ROBERTS        '
>>> re.sub('\s{2,}', '|', line.strip())
'ANDREWS VS BALL|JA-15-0050|D0015|JUDGE EDWARD A ROBERTS'

在应用之前从行中删除任何前导和尾随空格re.sub可确保您不会'|'在行的开头和结尾获得字符。

您的实际代码应与此类似:

import re
with open(filename) as f:
    for line in f:
        subbed = re.sub('\s{2,}', '|', line.strip())
        # do something here
于 2016-04-30T17:33:16.273 回答
5
s = """B, NICKOLAS                       CT144531X       D1026    JUDGE ANNIE WHITE JOHNSON  
ANDREWS VS BALL                   JA-15-0050      D0015    JUDGE EDWARD A ROBERTS
"""

# Update
re.sub(r"(\S)\ {2,}(\S)(\n?)", r"\1|\2\3", s)
In [71]: print re.sub(r"(\S)\ {2,}(\S)(\n?)", r"\1|\2\3", s)
B, NICKOLAS|CT144531X|D1026|JUDGE ANNIE WHITE JOHNSON  
ANDREWS VS BALL|JA-15-0050|D0015|JUDGE EDWARD A ROBERTS
于 2016-04-30T17:48:08.600 回答
3

考虑到至少有两个空格分隔列,您可以使用它:

lines = [
'B, NICKOLAS                       CT144531X       D1026    JUDGE ANNIE WHITE JOHNSON  ',
'ANDREWS VS BALL                   JA-15-0050      D0015    JUDGE EDWARD A ROBERTS        '
]

for line in lines:
    parts = []
    for part in line.split('  '):
        part = part.strip()
        if part:  # checking if stripped part is a non-empty string
            parts.append(part)
    print('|'.join(parts))

输入的输出:

B, NICKOLAS|CT144531X|D1026|JUDGE ANNIE WHITE JOHNSON
ANDREWS VS BALL|JA-15-0050|D0015|JUDGE EDWARD A ROBERTS
于 2016-04-30T17:27:47.857 回答
3

看起来您的数据采用“文本表”格式。

我建议使用第一行来确定每列的起点和长度(手动或使用正则表达式编写脚本以确定可能的列),然后编写脚本来迭代文件的行,将行分割成列段,并将条带应用于每个段。

如果您使用正则表达式,则必须跟踪列数并在任何给定行的列数超过预期的列数(或与其余列数不同)时引发错误。如果列的值有两个或多个空格,则在两个或多个空格上拆分会中断,这不仅完全可能,而且很可能。 像这样的文本表不是为了在正则表达式上拆分而设计的,它们是为了在列索引位置上拆分而设计的。

在保存数据方面,您可以使用 csv 模块写入/读取 csv 文件。这将使您比指定分隔符更好地处理引用和转义字符。如果您的列中有一个|字符作为值,除非您使用处理转义或引用文字的策略对数据进行编码,否则您的输出将在读取时中断。

解析上面的文本看起来像这样(我用括号而不是传统格式嵌套了一个列表理解,所以它更容易理解):

cols = ((0,34),
        (34, 50),
        (50, 59),
        (59, None),
        )
for line in lines:
    cleaned = [i.strip() for i in [line[s:e] for (s, e) in cols]]
    print cleaned

然后您可以使用以下内容编写它:

import csv
with open('output.csv', 'wb') as csvfile:
    spamwriter = csv.writer(csvfile, delimiter='|',
                            quotechar='"', quoting=csv.QUOTE_MINIMAL)
    for line in lines:
        spamwriter.writerow([line[col_start:col_end].strip()
                             for (col_start, col_end) in cols
                             ])
于 2016-04-30T18:00:02.317 回答
0

看起来这个库可以很好地解决这个问题:http: //docs.astropy.org/en/stable/io/ascii/fixed_width_gallery.html#fixed-width-gallery

感人的...

于 2016-05-12T21:13:59.663 回答