在python中读取文件时如何去除行末的换行符以及在Windows与Linux中的区别

本文详细介绍了在Python中读取文件时去除行末换行符的方法,并深入探讨了在Windows与Linux系统中处理换行符的区别。通过实例演示,讲解了不同环境下换行符的特性及最佳实践。

【时间】2018.11.14

【题目】在python中读取文件时如何去除行末的换行符以及在Windows与Linux中的区别

 

一、去除换行符

以使用readline进行读取为例:

import re

data =[]

f = open("data.txt", "r")

line = f.readline() # 读取一行文件,包括换行符

# line = line[:-1]  # 去掉换行符(方法1)

#line = re.sub('\n','',line) #方法2

line = line.strip() #方法3

data.append(line)

while line:  # 直到读取完文件

    line = f.readline()

    # line = line[:-1]

    #line = re.sub('\n','',line)

    line = line.strip() 

    if line != '':

     data.append(line)

f.close()

print(data)

 

二、在Windows与Linux中的区别

2.1windows

在window中,只要按照上面的代码即可去除换行符,即“\n”会直接被去掉,如下:

没有去掉换行符时:

去掉换行符后:

2.2.Linux

在Linux中,若直接去掉换行符(方法1与方法2),“\n”不会直接被去掉,而是会被‘\r’(回车符)代替,如下:

当然此时若再使用strip()也可以将‘\r’去除。

如果使用方法3,即用strip(),则可以去除:

所以建议使用方法3去除换行符。

 


2018.11.24补充

三、在Windows与Linux中换行符有所区别的原因

这主要是两种系统的换行符不同导致的,其中Linux的换行符时\n,而Windows的换行符是\r\n(就是说当你在文本编辑器中敲下回车键或者在代码中(w模式下)使用write(‘\n’)命令写入换行时,‘\n’会自动转换为‘\r\n’,读取时‘\r\n’会自动转换为‘\n’),当代码中的open是以‘r’模式打开时,两者没有区别,都是显示\n,而当以二进制模式‘rb’打开时,就会显现出不同。下面是在Windows和Linux中的测试(data.txt都是直接用各自系统的文本编辑器输入内容的。):

代码:

f = open('data.txt','r')
print(list(f))
f = open('data.txt','rb')
print(list(f))

Windows中运行结果:

Linux中运行结果:

因此,第二节中之所以出现在Linux中去除结尾的\n还剩下\r,是因为博主测试时的data.txt文件都是在Windows中编辑的,所以换行符在Windows中以文本方式显示是\n,在Linux中以文本方式显示的是\r\n。

 

 

<think>嗯,用户问的是在Linux中如何只在遇到换行符才输出内容到文件,避免冗余的动态内容。这个问题看起来是关于如何实处理命令的输出,但只保留完整的,而不是那些动态更新的部分,比如进度条之类的。 首先,我需要回想一下常见的动态输出是如何工作的。通常,程序会用回车符(\r)或者退格符(\b)来覆盖当前,实现进度更新。比如,一个进度条可能会显示“Progress: 20%”,然后用“\r”回到首,再显示“Progress: 50%”,最终显示“Progress: 100%”。这候,如果直接重定向输出到文件,可能会看到所有中间步骤,导致文件中有很多重复的或者不完整的。 用户的需求是希望只有在遇到换行符(\n)的候才将内容写入文件,这样每次写入的都是一整,而不是中间被覆盖的部分。这样的话,最终文件里只会有完整的,不会有那些动态变化的中间状态。 接下来,我需要考虑有哪些方法可以实现这一点。首先想到的是标准缓冲机制。通常,标准输出是缓冲的,也就是遇到换格符才会刷新缓冲区。但如果程序本身没有使用缓冲,或者输出到管道缓冲方式改变,可能需要其他方法。 可能的解决方案包括: 1. 使用工具如`stdbuf`来修改缓冲设置,强制缓冲。 2. 使用`grep`或者`sed`来匹配包含换行符。 3. 使用`awk`按处理,只在遇到换行符打印。 4. 利用`while`循环逐读取,并写入文件。 5. 处理特殊字符如回车符和退格符,确保只保留最终内容。 然后,需要具体分析每个方法的适用性。比如,`stdbuf`可以调整缓冲模式,但可能不是所有系统都支持,或者某些程序可能忽略这个设置。使用`grep`或`sed`的话,可能需要正则表达式来匹配尾的换行符,但要注意处理中间的回车符。`awk`在处理候比较灵活,可以逐处理,并且默认是按读取的,可能比较适合这个需求。而`while`循环在Bash中可以逐读取输入,并每次写入文件,这可能也是一个有效的方法。 另外,用户提到要避免冗余的动态内容,这可能涉及到过滤掉使用\r或\b的动态更新。比如,某些程序在更新进度不会输出换行符,而是用\r回到首覆盖之前的内容。这候,直接按换行符分割可能无法正确捕获最终结果,因为最后一次更新可能没有换行符。因此,可能需要结合处理\r的情况,确保在遇到换行符才输出,或者在没有换行符的情况下也能捕获最终状态。 例如,如果一个程序输出多,其中某些被动态更新,比如: Line 1: Progress: 20%\rProgress: 50%\rProgress: 100%\n Line 2: Done\n 这候,正确的处理应该是捕获“Progress: 100%”和“Done”作为两输出到文件。但如果使用普通的缓冲,可能会在每次遇到\r覆盖之前的,导致中间内容被写入。因此,需要确保只有在遇到\n才将当前(包括经过覆盖后的内容)写入文件。 可能需要结合之前提到的处理退格符和回车符的方法,先清理掉这些控制字符的影响,再按输出。例如,使用`sed`或`perl`处理掉\r和\b的影响,然后通过缓冲工具确保每次换行写入。 总结来说,可能的步骤包括: 1. 处理控制字符(\r, \b)以保留最终内容。 2. 确保输出在遇到换行符刷新到文件。 3. 使用适当的工具(如awk、sed、while循环)来逐处理并写入文件。 需要验证这些方法是否有效,比如测试一个动态更新的命令,看是否只保留最终结果并按写入文件。同,注意不同工具在不同环境下的兼容性,比如是否所有系统都支持`stdbuf`,或者`perl`的处理方式是否一致。 最后,可能需要给出几种不同的方法,让用户根据具体情况选择最适合的方案,比如是否能够修改程序源码、是否处理多更新、是否需要兼容不同控制字符等。</think>在 Linux 中,若希望**仅在遇到换行符 `\n` 才将内容输出到文件**(避免动态覆盖内容如 `\r` 或 `\b` 的影响),可通过以下方法实现: --- ### 方法 1:强制缓冲 + 过滤控制符 通过 `stdbuf` 强制程序使用缓冲模式,并配合过滤工具清理动态覆盖符: ```bash # 强制缓冲,处理 \r 和 \b 的控制符 your_command | stdbuf -oL tr -d '\r' | perl -pe 's/[^\x08]\x08//g while /\x08/' > output.log ``` **关键解释**: - `stdbuf -oL`:强制将输出流设为缓冲模式(`-oL` 表示 `stdout` 缓冲)。 - `tr -d '\r'`:删除回车符 `\r`(防止整覆盖)。 - `perl` 命令:递归处理退格符 `\b`(保留最终覆盖结果)。 - `>`:仅在遇到 `\n` 触发写入文件。 **示例**: 输入流为动态更新内容: ```bash echo -ne "Processing: 20%\rProcessing: 50%\rProcessing: 100%\nDone!\n" ``` 输出文件 `output.log` 内容: ``` Processing: 100% Done! ``` --- ### 方法 2:逐读取写入(Bash 循环) 通过 `while read` 逐读取输入流,仅在遇到换行符写入文件: ```bash your_command | { while IFS= read -r line; do echo "$line" >> output.log done } ``` **关键解释**: - `read -r line`:按换行符 `\n` 分割输入流,逐读取。 - `echo "$line" >> output.log`:每次读取完整后追加写入文件。 - 自动跳过中间未换行的动态更新(如 `\r` 覆盖)。 --- ### 方法 3:使用 `awk` 按输出 利用 `awk` 默认按处理的特性,直接写入文件: ```bash your_command | awk '{print $0}' > output.log ``` **等效简化**: ```bash your_command | awk '1' > output.log # '1' 为真,默认执 {print} ``` **关键为**: - `awk` 自动以 `\n` 为分隔符,每次读取完整后输出。 - 隐式跳过未换行的中间状态(如 `\r` 覆盖内容)。 --- ### 方法 4:结合控制符处理缓冲 若动态内容混合 `\r` 和 `\b`,先清理控制符再按写入: ```bash your_command \ | perl -pe 's/[^\x08]\x08//g while /\x08/' \ # 处理退格符 | sed 's/\r.*//' \ # 最后一次 \r 后的内容 | stdbuf -oL tee output.log # 按缓冲写入 ``` **示例输入流**: ```bash echo -ne "Step 1\b\b2: 20%\rStep 2: 50%\rFinal: 100%\n" ``` 输出文件内容: ``` Final: 100% ``` --- ### 方法 5:直接修改程序输出为 若可控制程序源码,强制在逻辑完成输出换行符: ```python # Python 示例:确保更新后显式换行 import time for i in range(1, 4): print(f"Progress: {i}/3", end='\r') # 动态覆盖 time.sleep(1) print("\nDone!") # 最终换行触发写入 ``` 执并重定向输出: ```bash python script.py > output.log ``` 文件内容: ``` Done! ``` --- ### 效果对比 | 方法 | 适用场景 | 优点 | 缺点 | |---------------------|----------------------------------|--------------------------|--------------------------| | 缓冲 + 过滤控制符 | 动态内容含 `\r` 或 `\b` | 彻底清理覆盖符 | 依赖外部工具(如 `perl`)| | Bash 逐读取 | 简单逐输出 | 无需额外工具 | 无法处理单动态更新 | | `awk` 按输出 | 快速过滤未换行内容 | 高效简洁 | 不处理 `\r` 覆盖内容 | | 源码显式换行 | 自主开发程序 | 精准控制输出机 | 需修改程序 | --- ### 注意事项 1. **动态单更新**: 若程序使用 `\r` 更新单且未换行(如进度条),需额外处理(如 [方法4](#方法-4结合控制符处理缓冲))才能捕获最终结果。 2. **缓冲机制**: - 管道默认使用全缓冲,可能延迟写入。 - 使用 `stdbuf -oL` 或 `unbuffer`(需安装 `expect`)强制缓冲。 3. **多动态效果**: 若程序同更新多(如日志+进度条),需更复杂解析(如 `ncurses` 库或终端录制工具)。 --- ### 最终推荐方案 - **简单场景**:直接用 `your_command > output.log`,大多数 CLI 工具默认在换行写入。 - **动态单更新**:使用 [方法1](#方法-1强制缓冲--过滤控制符) 或 [方法4](#方法-4结合控制符处理缓冲)。 - **自主开发程序**:显式在逻辑结束输出换行符([方法5](#方法-5直接修改程序输出为))。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值