如何从二进制文件中删除开始换行符或开始新行?

Posted

技术标签:

【中文标题】如何从二进制文件中删除开始换行符或开始新行?【英文标题】:How to remove starting newlines or the starting new from a binary file? 【发布时间】:2020-05-04 19:46:30 【问题描述】:

我看到有关于删除尾随换行符的讨论。

How can I delete a newline if it is the last character in a file?

但我没有找到关于删除起始换行符的讨论。任何人都可以让我知道删除开始换行符的最佳方法是什么(首选一个班轮)?谢谢。

【问题讨论】:

lstrip() ? replace也可以帮忙 您要删除所有初始空行,还是只删除第一个空行? 两者都需要。 你能举一个小的输入例子吗? 另外,为什么首选一个班轮 【参考方案1】:

chomp 等效的相反Perl 代码是s/^\n//。不要在最后一行 (eof) 上做,而是在第一行做。即使它只是一个空行,删除换行符将意味着该行不会在输出中打印任何内容。

perl -pe 's/^\n// if $. == 1' filename >filename2

或就地:

perl -pi -e 's/^\n// if $. == 1' filename

由于开始换行符定义为空行,因此您也可以使用 -n 而不是 -p 跳过打印它们(行为相同但不打印,因此您可以确定要打印哪些行)。

perl -ni -e 'print unless $. == 1 and m/^\n/' filename

如果您想删除潜在的多个起始换行符,您可以采取另一种方法;开始时自己推进句柄,直到收到非空行。

perl -pi -e 'if ($. == 1)  $_ = <> while m/^\n/ ' filename

如果您不介意一次将整个文件读入内存而不是逐行读入内存,这一切都会容易得多:

perl -0777 -pi -e 's/^\n+//' filename

为了避免在编辑文件时做任何多余的工作,除非它以换行符开头,您可以通过在编辑前加上另一个命令来调节编辑(读取文件的第一行,如果没有,则导致非零退出状态以换行符开始):

perl -e 'exit 1 unless <> =~ m/^\n/' filename && perl ...

【讨论】:

不要替换,如果只是换行,则跳过该行。 但我想这需要使用除了简单的perl -pie 循环之外的其他东西。 @Barmar 是的,你不能跳过-p 中的行,因为$_ 总是被打印出来。但是您可以使用-n 采取这种方法 - 会增加答案。 另外,问题说开始换行 - 复数。不过,我要求澄清。 我不太关注这个perl -pi -e 'if ($. == 1) $_ = &lt;&gt; while m/^\n/ ' filename。你能解释一下它是如何工作的吗?谢谢。【参考方案2】:

在 Python 中,开始读取文件而不是循环写入,直到出现非空行。

outdata = ""
with open(filename) as infile:
    while True:
        line = infile.readline()
        if line != "\n":
            break
    if line:
        outdata = line # save first non-empty line
    outdata += infile.read() # save the rest of the file
with open(filename, "w") as outfile:
    outfile.write(outdata)

【讨论】:

确保在没有任何非空行的情况下处理到达 eof @Grinnz 添加了if。这应该可以工作,因为它在 EOF 处返回一个空字符串。 连接所有将被写入字符串的行。然后关闭 infile 并将字符串写回原始文件。 @user1424739 原文件的就地编辑是什么意思? @AMC 他的意思是他想替换文件而不是创建一个新文件。【参考方案3】:

跳过前导空行的简单过滤器

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

my $begin = 1;

while( <> ) 
        next if /^$/ and $begin;
        $begin = 0;
        say;

一个班轮版本perl -0777 -pe 's/^\n+//' filename

【讨论】:

【参考方案4】:

这是我想出来的,我相信它仍然可以改进一点。

with open('../resources/temp_in.txt', 'r+') as file:
    overwrite = False
    for line in file:
        if line:
            overwrite = True
            first_line = line
            break
    if overwrite:
        contents = first_line + file.read()
        file.seek(0)
        file.write(contents)
        file.truncate()

这是另一种解决方案,它打开文件两次。

with open('../resources/temp_in.txt') as file:
    for line in file:
        if line.strip():
            contents = line + file.read()
            break
    else:
        contents = ''

with open('../resources/temp_in.txt', 'w') as file:
    file.write(contents)

【讨论】:

什么时候使用 seek 更好?什么时候关闭文件再重新打开比较好? @user1424739 什么时候使用 seek 更好? 而不是什么? 什么时候关闭文件再重新打开比较好?这取决于,关闭和重新打开如何适应其余的潜在解决方案? 解决方法可以是打开文件,将内容读入变量,关闭文件,去掉变量中的前导换行符,再次打开文件,将变量内容保存到文件中关闭它。这与您当前的解决方案性能有何不同。换句话说,寻找或关闭文件并重新打开它更快? @user1424739 嗯,我想这是个好问题,因为我实际上是在读/写整个文件,所以应该不会有太大的不同。我会想出一个快速的解决方案。 @user1424739 查看我的编辑。您是否有任何测试数据,以确保其完美运行?【参考方案5】:

当你找到一个不只是换行符的行时设置一个标志,并在设置该标志时打印:

awk '/./f=1f' file

例如:

$ printf '\n\n\nfoo\nbar\n'



foo
bar

$ printf '\n\n\nfoo\nbar\n' | awk '/./f=1f'
foo
bar

【讨论】:

以上是关于如何从二进制文件中删除开始换行符或开始新行?的主要内容,如果未能解决你的问题,请参考以下文章

从二进制文件创建 Numpy 数组的有效方法

从二进制文件中删除 protobuf c++ 编译的路径字符串

如何从二进制文件中读取块并使用 Python 或 Perl 解包提取结构?

在python中如何从二进制文件中读取信息

在 MFC 中从二进制文件加载图像

如何从二进制文件中获取应用程序的版本号?