【问题标题】:Handling \n vs ^M\n newlines with Python使用 Python 处理 \n vs ^M\n 换行符
【发布时间】:2019-09-18 11:26:25
【问题描述】:

我正在解析一个包含如下键值对的文件:

with open(filename) as f:
    data = f.read()
    key_value_pairs = data.split(";\n")

然后有一天,交付的文件有一个不同的行终止符,有人将处理它的那一行更改为:

key_value_pairs = data.split(";^M\n")

找到了答案here,它解释了^M 是MS-DOS 现象。

然后this answer 声称 Windows 终结符是 \r\n,没有提到 ^M\n

作为背景信息,将提到该列表中的每个元素 key_value_pairs 在另一个循环中进一步拆分为 .split("=", 1)

我希望将来的文件在有或没有^M 的情况下会出现不可预测的行终止,并试图找到一种方法来处理它,而无需使用混乱的正则表达式或字符串方法(如果可以避免的话)。

也许最好的办法是在开始时从文件中删除每个^M,然后将它们全部视为 Unix 文件。但是,对于文件中的某些 base64 二进制块,这可能有点危险。

在打开文件时,Python 中有什么东西可以干净地处理那些^M 吗?

【问题讨论】:

  • 这里的“交易”是什么意思?删除它们?将它们转换成别的东西?
  • 如果你的open 调用真的像这样,Python 应该会自动为你将\r\n 转换为\n。请参阅 open 函数的 newline 参数:docs.python.org/3.5/library/functions.html#open
  • 用换行符分割文件,不管有没有^M
  • 在文件中还没有看到\r,它看起来不像^M

标签: python python-3.x newline separator


【解决方案1】:

正如您提到的链接,^M 是 ASCII 字符 13,Python 应将其读取为 \r

您可以通过使用re.split 解析可选的\r 来完成此操作:

import re

data = 'split;\ntest;\r\nhere;\nanother;\r\nyay'

key_value_pairs = re.split(r';\r?\n', data)

# ['split', 'test', 'here', 'another', 'yay']

但是,如果是文字字符^M,则使用re.split(r';\^M\n|;\n', data)

data = 'split;\ntest;^M\nhere;\nanother;^M\nyay'

key_value_pairs = re.split(r';\^M\n|;\n', data)

# ['split', 'test', 'here', 'another', 'yay']

【讨论】:

  • 感谢@Krrr,我认为在阅读^M\r 时需要一点帮助。您能否添加一个替代正则表达式,它也将匹配^M\n,如果它存在而不是\r\n?做了一些实验,但不能让它工作。
  • 如前所述,我相信字符 ^M 在 Python 中被读取为 \r,因此这将是解析它的正确方法。这里的相关答案:stackoverflow.com/questions/11755208/… - 如果是文字字符^M,请使用re.split(r';\^M\n|;\n', data)
  • 感谢无论有没有^M 都能完美运行。为什么会有一个我不知道的“文字”字符,希望它不会再次发生,但如果它确实发生了,那么该正则表达式似乎可以正确处理它。
  • 这取决于数据在到达您的脚本之前通过的位置。某些处理可能已将 ASCII 字符 13 转换为文字字符 ^M 而不是原始字符。
  • 是的,这里的“一些处理”可能是在它到达python之前,会向管理它的人提及。用 ssh 传输文件的东西,肯定有一点可能出错。
猜你喜欢
  • 2011-06-03
  • 2017-06-03
  • 2015-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-27
  • 2018-10-21
相关资源
最近更新 更多