如何编写一个 awk
脚本(假设是一行代码),用于删除 BOM?
要求如下:
- 打印第一行之后的每一行 (
NR > 1
) - 对于第一行:如果以
#FE #FF
或#FF #FE
开头,则删除这些并打印其余部分
如何编写一个 awk
脚本(假设是一行代码),用于删除 BOM?
要求如下:
NR > 1
)#FE #FF
或 #FF #FE
开头,则删除这些并打印其余部分使用 GNU sed
(在 Linux 或 Cygwin 上):
# Removing BOM from all text files in current directory:
sed -i '1 s/^\xef\xbb\xbf//' *.txt
在FreeBSD操作系统上:
sed -i .bak '1 s/^\xef\xbb\xbf//' *.txt
使用GNU或FreeBSD sed
的优点是:-i
参数表示“原地”,可以在不需要重定向或奇怪技巧的情况下更新文件。
在Mac上:
另一个答案中的这个awk
解决方案有效,但上面的sed
命令无效。至少在Mac(Sierra)上,sed
文档没有提到支持十六进制转义字符,如\xef
。
任何程序都可以通过将其连接到sponge
工具来实现类似的技巧:
awk '…' INFILE | sponge INFILE
试试这个:
awk 'NR==1{sub(/^\xef\xbb\xbf/,"")}{print}' INFILE > OUTFILE
在第一条记录(行)中,移除BOM字符。打印每条记录。
或者稍微简短一些,利用awk的默认操作是打印记录:
awk 'NR==1{sub(/^\xef\xbb\xbf/,"")}1' INFILE > OUTFILE
1
是最短的条件,总是评估为真,因此每个记录都会被打印。
享受吧!
-- 补充 --
Unicode字节顺序标记(BOM)FAQ包括以下表格,列出了每种编码的确切BOM字节:
Bytes | Encoding Form
--------------------------------------
00 00 FE FF | UTF-32, big-endian
FF FE 00 00 | UTF-32, little-endian
FE FF | UTF-16, big-endian
FF FE | UTF-16, little-endian
EF BB BF | UTF-8
因此,您可以看到如何将\xef\xbb\xbf
与上表中的EF BB BF
UTF-8
BOM字节对应。
awk '{if(NR==1)sub(/^\xef\xbb\xbf/,"");print}' INFILE > OUTFILE
,确保INFILE和OUTFILE不同! - Steve Clayperl -i.orig -pe 's/^\x{FFFE}//' badfile
,你可以依靠你的 PERL_UNICODE 和/或 PERLIO 环境变量来确定编码方式。PERL_UNICODE=SD 适用于 UTF-8;对于其他编码,你需要使用 PERLIO。 - tchristawk 'NR==1{sub(/^\xef\xbb\xbf/,"")}1'
- TrueY不是awk,但更简单:
tail -c +4 UTF8 > UTF8.nobom
检查BOM:
hd -n 3 UTF8
如果存在BOM,你会看到:00000000 ef bb bf ...
cat file1.utf8 file2.utf8 file3.utf3 > allfiles.utf8
也会出问题。永远不要在UTF-8上使用BOM。句号。 - tchristif [[ "
file a.txt | grep -o 'with BOM'" == "BOM" ]];
- Benoit Duffezdos2unix
还会删除BOM:dos2unix *.txt
dos2unix
还会将带BOM的UTF-16文件(但没有BOM的UTF-16文件除外)转换为无BOM的UTF-8:
$ printf '\ufeffä\n'|iconv -f utf-8 -t utf-16be>bom-utf16be
$ printf '\ufeffä\n'|iconv -f utf-8 -t utf-16le>bom-utf16le
$ printf '\ufeffä\n'>bom-utf8
$ printf 'ä\n'|iconv -f utf-8 -t utf-16be>utf16be
$ printf 'ä\n'|iconv -f utf-8 -t utf-16le>utf16le
$ printf 'ä\n'>utf8
$ for f in *;do printf '%11s %s\n' $f $(xxd -p $f);done
bom-utf16be feff00e4000a
bom-utf16le fffee4000a00
bom-utf8 efbbbfc3a40a
utf16be 00e4000a
utf16le e4000a00
utf8 c3a40a
$ dos2unix -q *
$ for f in *;do printf '%11s %s\n' $f $(xxd -p $f);done
bom-utf16be c3a40a
bom-utf16le c3a40a
bom-utf8 c3a40a
utf16be 00e4000a
utf16le e4000a00
utf8 c3a40a
批处理运行器 -> 搜索(以查找子文件夹中的所有文件) -> 替换模板 -> 二进制删除BOM(有一个现成的搜索和替换模板可供使用)。
这不是最优雅的解决方案,需要安装一个程序,这是一个缺点。但是一旦我知道周围发生了什么,它就像魔术般地工作了(并找到了大约2300个文件中的3个带有BOM的文件)。
10.11.6
上,这个方法不起作用,但官方答案 https://dev59.com/t3NA5IYBdhLWcg3wKacx#1068700 可以正常工作。 - Heath Borders