仅当不存在换行符时才添加换行符
- 2024-11-01 08:41:00
- admin 原创
- 41
问题描述:
我想仅在文件末尾不存在换行符时才添加换行符。这是为了防止文件末尾出现多个换行符。
我希望使用sed
。以下是我当前代码遇到的问题:
sed -i -e '/^$/d;$G' /inputfile
echo file1
name1
name2
echo file2
name3
name4
(newline)
当我在文件上运行我的代码时;
echo file1
name1
name2
(newline)
echo file2
name3
name4
如果没有换行符,它会添加一个换行符;如果存在换行符,它会删除它……这让我很困惑。
解决方案 1:
sed
GNU:
sed -i '$a\' *.txt
操作系统:
sed -i '' '$a\' *.txt
$
解决最后一行。a
是附加函数。
OS X 的 sed
sed -i '' -n p *.txt
-n
禁用打印并p
打印模式空间。p
在 OS X 的 sed 中添加缺少的换行符,但在 GNU sed 中不添加,因此这不适用于 GNU sed。
awk
awk 1
1
(数字 1)可以替换为任何计算结果为 true 的值。 就地修改文件:
{ rm file;awk 1 >file; }<file
狂欢
[[ $(tail -c1 file) && -f file ]]&&echo ''>>file
尾随换行符将从命令替换的结果中删除,因此$(tail -c1 file)
仅当file
以换行符结尾或为空时才为空。-f file
如果为空则为 false file
。[[ $x ]]
相当于[[ -n $x ]]
bash 中的。
解决方案 2:
不必处理整个文件只是sed
为了在末尾添加一个换行符,只需检查最后一个字符,如果不是换行符,则添加一个。测试换行符有点意思,因为 shell 通常会从字符串末尾修剪它们,所以我附加了“x”来保护它:
if [ "$(tail -c1 "$inputfile"; echo x)" != $'
x' ]; then
echo "" >>"$inputfile"
fi
请注意,这会将换行符附加到空文件,这可能不是您想要的。如果您想保留空文件,请添加另一个测试:
if [ -s "$inputfile" ] && [ "$(tail -c1 "$inputfile"; echo x)" != $'
x' ]; then
echo "" >>"$inputfile"
fi
解决方案 3:
为方便起见,将诺曼的回答转换为拆分的单行。
for i in * ; do echo $i; \n if diff /dev/null "$i" | tail -1 | \n grep '^\\ No newline' > /dev/null; then echo >> "$i"; \n fi; done
将 * 替换为您想要的任何文件模式,例如*.c
另一个只是告诉您哪些文件已损坏:
for i in * ; do \n if diff /dev/null "$i" | tail -1 | \n grep '^\\ No newline' > /dev/null; then echo $i; \n fi; done
解决方案 4:
因为如果没有换行符它会删除换行符,所以您可以简单地使用:
echo "" >> file; sed -ie '/^$/d;$G' file; sed -ie '/^$/d;$G' file
添加换行符并删除所有内容,然后添加换行符。虽然方法不太优雅,但确实有效 :)
解决方案 5:
对于文件末尾“缺少”换行符的文件,一个简单的修复方法是使用 sed;下面“就地”修复文件(使用“-i”选项):
find . -type f -exec sed -i -e '$a\' {} ; -print
解释:
查找所有文件 (
-type f
),跑步
sed
,就地修改文件(
-i
),给定以下 (
-e
) 脚本/表达式,它与文件结尾匹配 ($
),并执行“附加”操作(
a
),但实际上并没有指定要附加的任何文本( 之后没有任何内容``),这将在文件末尾添加一个换行符,但只有当它丢失时才会这样做。
打印找到的所有文件(无论是否修复),这可能是不必要的。
主要需要注意的是,sed
功能在不同平台之间有所差异,因此-i
可能-e
支持也可能不支持/相同;例如,较旧的 Unix 或 MacOS 的奇怪之处可能需要略有不同的语法。
要仅对与特定后缀匹配的文件名进行操作,只需添加find path/to/dir -type f ( -name *.C -o -name *.h -o -name *.java ) -exec ...
解决方案 6:
如果您可以使用 Unix 工具,您可以运行diff
来找出哪些文件缺少换行符,然后将其附加:
#!/bin/sh
for i
do
if diff /dev/null "$i" | tail -1 | grep '^\\ No newline' > /dev/null
then
echo >> "$i"
fi
done
我依靠来生成第一列diff
带有 的消息 ,给我输出的最后一行,并告诉我最后一行是否是我要查找的消息。如果一切正常,则生成一个换行符,并将其附加到文件。周围的引号确保即使文件名中有空格,一切仍能正常工作。`tail
diffgrep
echo>>
"$i"`"$i"
解决方案 7:
好的,在评论中抱怨之后,我有一个更好的解决方案。首先,您要知道哪些文件缺少换行符:
find -type f -exec sh -c "tail -1 {} | xxd -p | tail -1 | grep -v 0a$" ';' -print
不是超级快(每个文件调用几个进程),但对于实际使用来说还可以。
现在,当您拥有它时,您也可以添加换行符,以及另一个-exec
:
find -type f -exec sh -c "tail -1 {} | xxd -p | tail -1 | grep -v 0a$" ';' -exec sh -c "echo >> {}" ';'
可能存在的陷阱:
如果文件名不好,例如有空格,则可能需要
tail -1 "{}"
。或者 find 做得对吗?您可能想要添加更多过滤功能来查找、喜欢
-name *py
或类似内容。使用前请考虑可能出现的 DOS/Unix 换行混乱问题(先修复它)。
编辑:
如果您不喜欢这些命令的输出(回显一些十六进制),请添加-q
到 grep:
find -type f -exec sh -c "tail -1 {} | xxd -p | tail -1 | grep -q -v 0a$" ';' -print
find -type f -exec sh -c "tail -1 {} | xxd -p | tail -1 | grep -q -v 0a$" ';' -exec sh -c "echo >> {}" ';'
解决方案 8:
tail -c1 file | read -r _ || echo >> file
获取文件的最后一个字符read
,将其导入,如果在换行符之前遇到 EOF(因此,如果文件的最后一个字符不是换行符),它将以非零退出代码退出。如果read
退出非零,则使用将换行符附加到文件上echo
(如果read
退出 0,则满足||
,因此echo
命令不会运行)。
摘自http://backreference.org/2010/05/23/sanitizing-files-with-no-trailing-newline/。
解决方案 9:
尝试 ex-way:
ex -s +"bufdo wq" *.c
并递归(启用新的通配符选项):
ex -s +"bufdo wq" **/*.c
这相当于vi -es
。更改*.c
为您兴趣的延伸。
如果不存在ex
/,则在保存时会自动添加换行符。vi
解决方案 10:
仅使用 Bash
您可以将命令替换(删除尾随换行符)与此处字符串(附加换行符)结合使用:
Command Substitution
Command substitution allows the output of a command to replace the command name. There are two
forms:
$(command)
or
`command`
Bash performs the expansion by executing command in a subshell environment and replacing the com-
mand substitution with the standard output of the command, with any trailing newlines deleted.
Embedded newlines are not deleted, but they may be removed during word splitting. The command sub-
stitution $(cat file) can be replaced by the equivalent but faster $(< file).
Here Strings
A variant of here documents, the format is:
[n]<<<word
The word undergoes brace expansion, tilde expansion, parameter and variable expansion, command sub-
stitution, arithmetic expansion, and quote removal. Pathname expansion and word splitting are not
performed. The result is supplied as a single string, with a newline appended, to the command on
its standard input (or file descriptor n if n is specified).
工作原理如下:
cat <<<"$(<inputfile)"
输出到文件:
cat <<<"$(<inputfile)" >outputfile
如果您需要inputfile
并且outputfile
使用相同的文件名,您有几个选择 - 使用sponge
命令,使用更多命令替换保存到临时变量,或保存到临时文件。
使用 Sed
其他人建议使用
sed '$a\' inputfile
它在最后一行不添加任何内容。这很好,但我认为
sed '$q' inputfile
更清晰一些,因为它在最后一行退出。或者你可以这样做
sed -n 'p'
它用于-n
抑制输出,但是用 将其打印出来p
。
在任何这些情况下,sed
都会修复行并添加换行符,至少对于 GNU 和 BSD sed 而言是这样。但是,我不确定此功能是否由 POSIX 定义。的版本sed
可能会跳过没有换行符的行,因为行定义为
零个或多个非 <newline> 字符加上终止 <newline> 字符的序列。
解决方案 11:
使用 awk :
awk '/^$/{f=1}END{ if (!f) {print "
"}}1' inputfile
匹配空白行^$
(就像你所做的一样)并设置一个标志。如果末尾没有设置标志,则放置换行符。
注意:这`是在 OS X 中。可
`用于其他。
解决方案 12:
我很惊讶没有人提到许多简单的文本处理工具(如 Awk)会添加换行符作为副作用。这是一个简单的循环,只有实际添加了换行符时才会覆盖文件。
for f in *; do
awk 1 "$f" >tmp
cmp -s tmp "$f" || mv tmp "$f"
done
rm -f tmp
(临时文件显然有点问题。)
IDEone 演示:http://ideone.com/HpRHcx
解决方案 13:
尝试使用vi
或ex
:
ex -scwq foo.txt
或对于多个文件:
vi -es +"bufdo wq" *.txt
ex -s +"bufdo wq" *.txt
如果缺失,则在文件保存时自动在 EOF 处添加 EOL。
要递归地申请某些文件,请使用新的通配符选项( **
),例如**/*.txt
(enable by shopt -s globstar
)。
解决方案 14:
如果它有用,那么对我来说通常这样的方法有效:
printf "%s
" "$(cat file_that_MIGHT_need_a_NL.txt)"
这不是最优雅的解决方案,但是它允许我使用诸如、等工具,sed
而grep
不仅仅是cat
在那里。
当然,任何有效的变量或字符串也应该可以起作用。
年龄变化率
解决方案 15:
find -type f | while read f; do [[
tail -c1 "$f" ]] && echo >> "$f"; done
我使用find
而不是for f in *
因为它是递归的并且问题是关于“大量的源文件”。
我出于性能原因使用它while read
来代替find -exec
或xargs
,它每次都会节省生成 shell 进程。
我利用了反引号运算符返回命令输出“删除所有尾随换行符”的事实man bash
,因此对于正确终止的文件,反引号将为空并且将跳过回显。
这find | read
对操作将会在包含换行符的文件名上失败,但如果需要的话很容易修复:
find -type f -print0 | while read -d $' ' f; do [[
tail -c1 "$f" ]] && echo >> "$f"; done
解决方案 16:
以下是我的 bash 脚本解决方案。它首先检查文件是否为文本文件。然后,如果是文本文件,它使用 tail 和 od(八进制转储)查看最后一个字符是否为换行符。如果不是,则使用 echo 添加换行符:
item="$1"
if file "$item" | egrep 'text' > /dev/null
then
if ! tail -c 1 "$item" | od -b -A n | egrep '012' > /dev/null
then
echo "(appending final newline to ${item})"
echo >> "$item"
fi
fi
解决方案 17:
从 dos2unix 7.5.0 开始,您可以使用 -e 或 --add-eol 选项在最后一行添加换行符(前提是它还不存在):
dos2unix -e file.txt
要检查最后一行是否有换行符,请输入
dos2unix -e -ih file.txt
它将打印换行符的类型 (dos/unix/mac) 或 noeol(如果没有)。
解决方案 18:
由于命令本地化 Tim 和 Norman 的回答应使用 'LANG=C' 前缀进行改进,以便有机会将 '无换行符' 模式与具有任何区域参数的每个系统进行匹配
这确保了此脚本命令行上放置的每个文件都有一个空行:
#!/bin/sh -f
for i in $* ; do echo $i; \n if LANG=C diff /dev/null "$i" | tail -1 | \n grep '^\\ No newline' > /dev/null; then echo >> "$i"; \n fi; done
此脚本检测缺少的文件:
#!/bin/sh -f
for i in $* ; do \n if LANG=C diff /dev/null "$i" | tail -1 | \n grep '^\\ No newline' > /dev/null; then echo $i; \n fi; done
解决方案 19:
我通过使用dos2unix
(或对应物)标志解决了这个任务--newline
。优点是这些工具可以自行检测二进制文件。我喜欢使用的解决方案,tail -c1
但事先过滤二进制文件对我来说真的很慢。
dos2unix --newline my_file.txt
最后,我编写了一个脚本,搜索我的项目目录,将文件(, )之外的所有文件转换为LF
( ) ,并使用标志通过一次调用获得正确的换行符。dos2unix
`*.cmdCRLF
unix2dos`
解决方案 20:
找到这个工具后,我决定自己写一个
这是我的 Python 脚本,用于完成这项工作
它仅将 (\r\n) 附加到文件,而不在文件末尾包含 (\n)
https://github.com/tranhuanltv/append_newline
用法:append_newline.py .c ./projects ./result_dir
如果你想的话,可以提出 Pull 请求
解决方案 21:
pcregrep --recursive --exclude-dir=.git \n --files-without-match --multiline '
z' . |
while read k ; do echo >> "$k"; done
这里涉及几个步骤:
递归查找文件
检测哪些文件缺少尾随换行符
循环遍历每个文件
追加换行符
步骤 1 按照传统方式使用find
(遵循 Unix 传统“每个工具只做一件事,并做好它”),但由于 pcregrep 具有内置支持,因此我使用它很舒服。我小心避免弄乱 .git 文件夹。
第 2 步是通过多行正则表达式匹配具有最终换行符的文件并打印不匹配的文件的名称来完成的。
步骤 3 使用 while/read 循环而不是 for/in 完成,因为后者无法处理带有空格的文件名和极长的文件列表。
步骤 4 是一个简单的回声,遵循@norman-ramsey 的方法。
h/t @anthony-bush https://stackoverflow.com/a/20687956/577438了解 pcregrep 建议。
解决方案 22:
存在一种使用标准 shell 命令的优雅解决方案:
tail -c 1 file.txt | read || echo >> file.txt
tail
输出文件的最后一个字节read
将一行读入变量。如果未指定变量,则不执行任何操作,但如果 EOF 出现在换行符之前,则以代码 1 退出。echo
仅当读取失败时运行(即如果最后一个字符不是换行符),并将换行符附加到file.txt
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件