Linux 如果换行符是文件中的最后一个字符,如何删除换行符?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1654021/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I delete a newline if it is the last character in a file?
提问by Todd Partridge 'Gen2ly'
I have some files that I'd like to delete the last newline if it is the last character in a file. od -c
shows me that the command I run does write the file with a trailing new line:
我有一些文件,如果它是文件中的最后一个字符,我想删除最后一个换行符。 od -c
向我显示我运行的命令确实使用尾随新行写入文件:
0013600 n t > \n
I've tried a few tricks with sed but the best I could think of isn't doing the trick:
我已经尝试了一些使用 sed 的技巧,但我能想到的最好的方法是没有做到这一点:
sed -e '$s/\(.*\)\n$//' abc
Any ideas how to do this?
任何想法如何做到这一点?
采纳答案by pavium
perl -pe 'chomp if eof' filename >filename2
or, to edit the file in place:
或者,就地编辑文件:
perl -pi -e 'chomp if eof' filename
[Editor's note: -pi -e
was originally -pie
, but, as noted by several commenters and explained by @hvd, the latter doesn't work.]
[编者注:-pi -e
最初是-pie
,但是,正如几位评论者所指出并由@hvd 解释的那样,后者不起作用。]
This was described as a 'perl blasphemy' on the awk website I saw.
在我看到的 awk 网站上,这被描述为“对 perl 的亵渎”。
But, in a test, it worked.
但是,在测试中,它奏效了。
回答by Sinan ünür
$ perl -e 'local $/; $_ = <>; s/\n$//; print' a-text-file.txt
See also Match any character (including newlines) in sed.
另请参阅匹配 sed 中的任何字符(包括换行符)。
回答by Paused until further notice.
head -n -1 abc > newfile
tail -n 1 abc | tr -d '\n' >> newfile
Edit 2:
编辑2:
Here is an awk
version (corrected)that doesn't accumulate a potentially huge array:
这是一个不会累积潜在巨大数组的awk
版本(已更正):
awk '{if (line) print line; line=$0} END {printf $0}' abc
awk '{if (line) 打印行; line=$0} END {printf $0}' abc
回答by ghostdog74
gawk
呆呆的
awk '{q=p;p=perl -i -p0777we's/\n\z//' filename
}NR>1{print q}END{ORS = ""; print p}' file
回答by ysth
Yet another perl WTDI:
另一个 perl WTDI:
use autodie qw(open sysseek sysread truncate);
my $file = shift;
open my $fh, '+>>', $file;
my $pos = tell $fh;
sysseek $fh, $pos - 1, 0;
sysread $fh, my $buf, 1 or die 'No data to read?';
if($buf eq "\n"){
truncate $fh, $pos - 1;
}
回答by dlamblin
The only time I've wanted to do this is for code golf, and then I've just copied my code out of the file and pasted it into an echo -n 'content'>file
statement.
我唯一想这样做的是代码高尔夫,然后我刚刚从文件中复制了我的代码并将其粘贴到echo -n 'content'>file
语句中。
回答by jrockway
If you want to do it right, you need something like this:
如果你想把它做对,你需要这样的东西:
#!/usr/bin/python
# strip newline from last line of a file
import sys
def trunc(filename, new_len):
try:
# open with mode "append" so we have permission to modify
# cannot open with mode "write" because that clobbers the file!
f = open(filename, "ab")
f.truncate(new_len)
f.close()
except IOError:
print "cannot write to file:", filename
sys.exit(2)
# get input argument
if len(sys.argv) == 2:
filename = sys.argv[1]
else:
filename = "--help" # wrong number of arguments so print help
if filename == "--help" or filename == "-h" or filename == "/?":
print "Usage: %s <filename>" % sys.argv[0]
print "Strips a newline off the last line of a file."
sys.exit(1)
try:
# must have mode "b" (binary) to allow f.seek() with negative offset
f = open(filename, "rb")
except IOError:
print "file does not exist:", filename
sys.exit(2)
SEEK_EOF = 2
f.seek(-2, SEEK_EOF) # seek to two bytes before end of file
end_pos = f.tell()
line = f.read()
f.close()
if line.endswith("\r\n"):
trunc(filename, end_pos)
elif line.endswith("\n"):
trunc(filename, end_pos + 1)
We open the file for reading and appending; opening for appending means that we are already seek
ed to the end of the file. We then get the numerical position of the end of the file with tell
. We use that number to seek back one character, and then we read that one character. If it's a newline, we truncate the file to the character before that newline, otherwise, we do nothing.
我们打开文件进行读取和追加;open for append 意味着我们已经被seek
编辑到文件的末尾。然后我们得到文件末尾的数字位置tell
。我们使用这个数字来寻找一个字符,然后我们读取那个字符。如果是换行符,我们将文件截断为该换行符之前的字符,否则,我们什么都不做。
This runs in constant time and constant space for any input, and doesn't require any more disk space, either.
这对于任何输入都以恒定的时间和恒定的空间运行,并且也不需要更多的磁盘空间。
回答by steveha
Here is a nice, tidy Python solution. I made no attempt to be terse here.
这是一个不错的、整洁的 Python 解决方案。我没有试图在这里简洁。
This modifies the file in-place, rather than making a copy of the file and stripping the newline from the last line of the copy. If the file is large, this will be much faster than the Perl solution that was chosen as the best answer.
这会就地修改文件,而不是制作文件的副本并从副本的最后一行剥离换行符。如果文件很大,这将比被选为最佳答案的 Perl 解决方案快得多。
It truncates a file by two bytes if the last two bytes are CR/LF, or by one byte if the last byte is LF. It does not attempt to modify the file if the last byte(s) are not (CR)LF. It handles errors. Tested in Python 2.6.
如果最后两个字节是 CR/LF,则将文件截断两个字节,如果最后一个字节是 LF,则截断一个字节。如果最后一个字节不是 (CR)LF,它不会尝试修改文件。它处理错误。在 Python 2.6 中测试。
Put this in a file called "striplast" and chmod +x striplast
.
把它放在一个名为“striplast”的文件中,并且chmod +x striplast
.
import sys
sys.stdout.write(sys.stdin.read().rstrip("\n"))
P.S. In the spirit of "Perl golf", here's my shortest Python solution. It slurps the whole file from standard input into memory, strips all newlines off the end, and writes the result to standard output. Not as terse as the Perl; you just can't beat Perl for little tricky fast stuff like this.
PS 本着“Perl 高尔夫”的精神,这是我最短的 Python 解决方案。它将整个文件从标准输入拖入内存,去掉末尾的所有换行符,并将结果写入标准输出。不像 Perl 那样简洁;你就是无法在像这样一些棘手的快速东西上击败 Perl。
Remove the "\n" from the call to .rstrip()
and it will strip all white space from the end of the file, including multiple blank lines.
从调用中删除“\n” .rstrip()
,它将去除文件末尾的所有空白,包括多个空行。
Put this into "slurp_and_chomp.py" and then run python slurp_and_chomp.py < inputfile > outputfile
.
将其放入“slurp_and_chomp.py”中,然后运行python slurp_and_chomp.py < inputfile > outputfile
.
sed ':a;/^\n*$/{$d;N;};/\n$/ba' file
回答by ghostdog74
file='/path/to/file'
[[ "$(tail -c 1 "${file}" | tr -dc '\n' | wc -c)" -eq 1 ]] && \
printf "" | dd of="${file}" seek=$(($(stat -f "%z" "${file}") - 1)) bs=1 count=1
#printf "" | dd of="${file}" seek=$(($(wc -c < "${file}") - 1)) bs=1 count=1
回答by cpit
Using dd:
使用 dd:
##代码##