如何从二进制文件中删除开始换行符或开始新行?
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) $_ = <> 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
【讨论】:
以上是关于如何从二进制文件中删除开始换行符或开始新行?的主要内容,如果未能解决你的问题,请参考以下文章
从二进制文件中删除 protobuf c++ 编译的路径字符串