【问题标题】:How to convert CRLF to LF on a Windows machine in Python如何在 Python 中的 Windows 机器上将 CRLF 转换为 LF
【发布时间】:2023-04-04 15:23:02
【问题描述】:

所以我得到了那些模板,它们都以 LF 结尾,我可以在里面填写一些格式的术语,仍然可以通过 "wb" 打开来获取 LF 文件。

这些模板用于 Windows 机器上的部署脚本中,以在 unix 服务器上进行部署。

问题是,很多人会弄乱这些模板,我 100% 肯定他们中的一些人会在里面放一些 CRLF。

如何使用 Python 将所有 CRLF 转换为 LF?

【问题讨论】:

    标签: python python-2.7


    【解决方案1】:

    就地转换行尾(使用 Python 3)

    行尾:

    • Windows - \r\n,称为CRLF
    • Linux/Unix/MacOS - \n,称为LF

    Windows 到 Linux/Unix/MacOS (CRLFLF)

    这是一个简短的 Python 脚本,用于将 Windows 行尾直接转换为 Linux/Unix/MacOS 行尾。该脚本就地工作,即无需创建额外的输出文件。

    # replacement strings
    WINDOWS_LINE_ENDING = b'\r\n'
    UNIX_LINE_ENDING = b'\n'
    
    # relative or absolute file path, e.g.:
    file_path = r"c:\Users\Username\Desktop\file.txt"
    
    with open(file_path, 'rb') as open_file:
        content = open_file.read()
        
    # Windows ➡ Unix
    content = content.replace(WINDOWS_LINE_ENDING, UNIX_LINE_ENDING)
    
    # Unix ➡ Windows
    # content = content.replace(UNIX_LINE_ENDING, WINDOWS_LINE_ENDING)
    
    with open(file_path, 'wb') as open_file:
        open_file.write(content)
    

    Linux/Unix/MacOS 到 Windows (LFCRLF)

    要将转换从 Linux/Unix/MacOS 更改为 Windows,只需将 Unix ➡ Windows 的替换注释回来(删除行前的 #)。

    请勿注释掉Windows ➡ Unix 替换的命令,因为它可以确保正确转换。从LR 转换为CRLF 时,文件中不存在CRLF 行结尾很重要。否则,这些行将被转换为CRCRLF。首先将行从CRLF 转换为LF,然后将行从LF 转换为CRLF 将避免此问题(感谢@neuralmer 指出这一点)。


    代码说明

    二进制模式

    重要提示:我们需要确保以二进制模式(mode='rb'mode='wb')两次打开文件,才能进行转换。

    当以文本模式打开文件时(mode='r'mode='w' 不带b),平台的本机行尾(Windows 上的\r\n 和旧 Mac OS 版本上的\r)会自动转换为 Python 的 Unix -风格的行尾:\n。所以对content.replace() 的调用找不到任何\r\n 行尾要替换。

    在二进制模式下,不会进行此类转换。因此,对str.replace() 的调用可以完成它的工作。

    二进制字符串

    在 Python 3 中,如果未另行声明,字符串将存储为 Unicode (UTF-8)。但是我们以二进制模式打开文件 - 因此我们需要在替换字符串前面添加 b 以告诉 Python 也将这些字符串作为二进制处理。

    原始字符串

    在 Windows 上,路径分隔符是反斜杠 \,我们需要在普通 Python 字符串中使用 \\ 对其进行转义。通过在字符串前面添加r,我们创建了一个不需要任何转义的所谓“原始字符串”。因此,您可以直接将路径从 Windows 资源管理器复制/粘贴到您的脚本中。

    提示:在 Windows 资源管理器中按 CTRL+L 自动从地址栏中选择路径。)

    替代解决方案

    我们打开文件两次以避免重新定位文件指针。我们也可以使用mode='rb+' 打开文件一次,但是我们需要在读取其内容 (open_file.seek(0)) 后将指针移回开始并在写入新内容之前截断其原始内容 (open_file.truncate(0))。

    只需在写入模式下再次打开文件,我们就会自动完成。

    干杯和快乐的编程,
    眨眼

    【讨论】:

    • 我没有从文件中获取我的content,因此无法以二进制模式读取。基本上我有一个“多行字符串”。因此,我得到TypeError: replace() argument 1 must be str, not bytes。有解决办法吗?
    • @AstroFloyd 您首先需要将字符串转换为字节:byte_str = your_str.encode("UTF-8")。然后替换byte_str 的行尾。要将其转换回字符串,请使用:your_new_str = byte_str.decode("UTF-8").
    • 谢谢,我在 windows 中用 'w' 打开我的文件,但它被转换为 crlf。所以这对我来说不是真的:opening files in text mode (mode='r' or mode='w' without b), the platform's native line endings (\r\n on Windows and \r on old Mac OS versions) are automatically converted to Python's Unix-style line endings: \n
    • @Timo 根据官方documentation 的开放功能:“允许有一个额外的模式字符'U',它不再有任何作用,被认为已弃用。它以前启用文本模式下的通用换行符,这成为 Python 3.0 中的默认行为。有关更多详细信息,请参阅换行参数的文档。注意 Python 不依赖于底层操作系统的文本文件概念;所有处理均由 Python 完成本身,因此与平台无关。”
    • 为了将 LF 转换为 CRLF 行尾,重要的是要知道没有任何行已经以 CRLF 结尾,否则你可能会得到一些“以”CR CR LF 结尾的行.先将行从 CRLF 转换为 LF,然后再从 LF 转换为 CRLF 将避免此问题。
    【解决方案2】:

    Python 3:

    open 的默认换行符类型是通用的,在这种情况下,它不介意每行有哪种换行符。 您还可以使用 newline 参数为 open 请求特定形式的换行符。

    因此在 Python 中从一种形式转换为另一种形式相当简单:

    with open('filename.in', 'r') as infile, \
         open('filename.out', 'w', newline='\n') as outfile:
        outfile.writelines(infile.readlines())
    

    Python 2:

    open 函数通过'rU' 模式支持universal newlines

    再次,从一种形式转换为另一种形式:

    with open('filename.in', 'rU') as infile, \
         open('filename.out', 'w', newline='\n') as outfile:
        outfile.writelines(infile.readlines())
    

    (在 Python 3 中,模式 U 实际上已被弃用;等效形式为 newline=None,这是默认的)

    【讨论】:

      【解决方案3】:

      你为什么不试试下面:

      str.replace('\r\n','\n');
      

      CRLF => \r\n
      LF => \n

      【讨论】:

      • 它不会像这样工作,因为 python 将 \n 更改为当前系统默认行结尾(对于 Windows 是 CRLF)。因此,您需要使用二进制模式(不阻止 python 进行任何更改)或使用newline 参数,如赞成的答案所示。
      【解决方案4】:

      可以用以下代码来修复现有的模板:

      with open('file.tpl') as template:
         lines = [line.replace('\r\n', '\n') for line in template]
      with open('file.tpl', 'w') as template:
         template.writelines(lines)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-09-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-19
        • 1970-01-01
        • 2011-02-06
        相关资源
        最近更新 更多