我有大量的源文件,最后都缺少换行符。
如何自动在每一行的末尾添加换行符?
有些可能已有换行符,因此只应在必要时添加。
我可能不会寻找代码本身,但只是我可以在终端中运行以添加必要的换行符(或某种编程或开发工具)。
答案 0 :(得分:7)
如果您可以访问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
的邮件,以便为我提供diff
输出的最后一行,和grep
告诉我最后一行是否是我正在寻找的消息。如果一切正常,则echo
会生成换行符,>>
会将其附加到文件"$i"
。 "$i"
周围的引号可确保文件名中包含空格时仍可正常工作。
答案 1 :(得分:5)
为方便起见,将Norman的答案转换为拆分单行。
for i in * ; do echo $i; \
if diff /dev/null "$i" | tail -1 | \
grep '^\\ No newline' > /dev/null; then echo >> "$i"; \
fi; done
用您想要的任何文件模式替换*,例如*.c
另一个只是告诉你哪些文件坏了:
for i in * ; do \
if diff /dev/null "$i" | tail -1 | \
grep '^\\ No newline' > /dev/null; then echo $i; \
fi; done
答案 2 :(得分:4)
对缺少"缺少的文件的简单修复"文件末尾的换行符就是sed;以下修复了文件"就地" (使用" -i"选项):
find . -type f -exec sed -i -e '$a\' {} \; -print
说明:找到所有文件(-type f
),运行sed
,就地更改文件(-i
),给定以下(-e
)脚本/表达式,匹配文件的末尾($
),并执行"追加"操作(a\
),但实际上并未指定要追加的任何文本(\
之后没有任何内容),这将在文件末尾添加换行符,但仅限于&# 39;失踪。打印找到的所有文件(固定与否),这可能是不必要的。
主要警告是sed
功能因平台而异,因此-i
和-e
可能支持也可能不支持/相同;例如较旧的Unix或MacOS奇怪可能需要稍微不同的语法。
答案 3 :(得分:3)
好的,在评论中抱怨之后,有更好的解决方案。 首先,您想知道哪些文件缺少换行符:
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 \"{}\"
。
或者找到做对了吗?
您可能希望添加更多过滤功能,例如-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 >> {}" ';'
答案 4 :(得分:1)
尝试前方:
ex -s +"bufdo wq" *.c
递归(启用a new globbing option):
ex -s +"bufdo wq" **/*.c
这相当于vi -es
。将*.c
更改为您感兴趣的扩展名。
ex
/ vi
如果不存在,会自动在保存时添加换行符。
答案 5 :(得分:1)
以下是我的bash脚本解决方案。它首先检查该文件是否为文本文件。然后,如果它是一个文本文件,它使用tail和od(八进制转储)来查看最后一个字符是否是换行符。如果不是,则使用echo附加换行符:
item="$1"
if file "$item" | egrep '\btext\b' > /dev/null
then
if ! tail -c 1 "$item" | od -b -A n | egrep '\b012\b' > /dev/null
then
echo "(appending final newline to ${item})"
echo >> "$item"
fi
fi
答案 6 :(得分:0)
由于命令本地化,Tim和Norman回答应使用'LANG = C'前缀进行改进,以便有机会与具有任何区域参数的每个系统匹配'无换行'模式
这确保了放在此脚本命令行上的每个文件的结束空行:
#!/bin/sh -f
for i in $* ; do echo $i; \
if LANG=C diff /dev/null "$i" | tail -1 | \
grep '^\\ No newline' > /dev/null; then echo >> "$i"; \
fi; done
此脚本检测缺少它的文件:
#!/bin/sh -f
for i in $* ; do \
if LANG=C diff /dev/null "$i" | tail -1 | \
grep '^\\ No newline' > /dev/null; then echo $i; \
fi; done
答案 7 :(得分:0)
找到工具后做这项工作没有运气。我决定写自己的
这是我做这项工作的python脚本
它只附加(\ r \ n)文件末尾的文件不包含(\ n)
https://github.com/tranhuanltv/append_newline
用法:append_newline.py .c ./projects ./result_dir
如果您想
,请提出拉取请求答案 8 :(得分:0)
我很惊讶没有人提到像Awk这样的许多简单的文本处理工具会添加换行符作为副作用。这是一个简单的循环,只有在实际添加换行符时才会覆盖文件。
13
(临时文件显然有点像疣。)
IDEone演示:http://ideone.com/HpRHcx
答案 9 :(得分:0)
pcregrep --recursive --exclude-dir=.git \
--files-without-match --multiline '\n\z' . |
while read k ; do echo >> "$k"; done
这里涉及以下几个步骤:
传统上,步骤1使用find
(遵循Unix的传统)
"每个工具做一件事并且做得很好"),但由于pcregrep有内置的支持,我很舒服地使用它。我小心翼翼地避免弄乱.git文件夹。
第2步是使用多行正则表达式匹配做具有最终换行符的文件,并打印不匹配的文件的名称。< / p>
第3步是使用while / read循环而不是for / in完成的,因为后者对于带有空格的文件名和极长的文件列表都失败了。
第4步是一个简单的回声,遵循@ norman-ramsey的方法。
h / t @ anthony-bush https://stackoverflow.com/a/20687956/577438了解pcregrep建议。