使用awk删除字节顺序标记

Bol*_*wyn 102 unicode awk byte-order-mark

awk用于删除BOM的脚本(可能是单线程)怎么样?

规格:

  • 在第一个(NR > 1)之后打印每一行
  • 对于第一行:如果以#FE #FF或开头#FF #FE,则删除它们并打印其余部分

Den*_*aia 122

使用GNU sed(在Linux或Cygwin上):

# Removing BOM from all text files in current directory:
sed -i '1 s/^\xef\xbb\xbf//' *.txt
Run Code Online (Sandbox Code Playgroud)

在FreeBSD上:

sed -i .bak '1 s/^\xef\xbb\xbf//' *.txt
Run Code Online (Sandbox Code Playgroud)

使用GNU或FreeBSD的优点sed:-i参数意味着"就地",并且将更新文件而无需重定向或奇怪的技巧.

在Mac上:

awk解决方案的另一种回答的作品,但sed上面命令不起作用.至少在Mac(Sierra)sed文档中没有提到支持十六进制转义ala \xef.

通过spongemoreutils管道到工具,任何程序都可以实现类似的技巧:

awk '…' INFILE | sponge INFILE
Run Code Online (Sandbox Code Playgroud)

  • 我在Mac OS X上精确地尝试了第二个命令,结果是"成功",但替换实际上并没有发生. (5认同)
  • 当我在OS X上尝试使用0xef 0xbb 0xbf作为BOM的文件上的第二个命令时,它实际上没有进行替换. (3认同)

Bar*_*osz 111

试试这个:

awk 'NR==1{sub(/^\xef\xbb\xbf/,"")}{print}' INFILE > OUTFILE
Run Code Online (Sandbox Code Playgroud)

在第一个记录(行)上,删除BOM字符.打印每条记录.

或略短,使用awk中的默认操作来打印记录的知识:

awk 'NR==1{sub(/^\xef\xbb\xbf/,"")}1' INFILE > OUTFILE
Run Code Online (Sandbox Code Playgroud)

1 是始终评估为真的最短条件,因此每条记录都会打印出来.

请享用!

- 附加 -

Unicode字节顺序标记(BOM)常见问题解答包括下表,其中列出了每种编码的确切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
Run Code Online (Sandbox Code Playgroud)

因此,您可以看到如何\xef\xbb\xbfEF BB BF UTF-8上表中的BOM字节对应.

  • 但是,此解决方案仅适用于UTF-8编码文件**.对于其他人,如UTF-16,请参阅Wikipedia以获取相应的BOM表示:http://en.wikipedia.org/wiki/Byte_order_mark (5认同)
  • 所以:'awk'{if(NR == 1)sub(/ ^\xef\xbb\xbf /,""); print}'INFILE> OUTFILE`并确保INFILE和OUTFILE不同! (2认同)

Ste*_*lay 41

不是awk,而是更简单:

tail -c +4 UTF8 > UTF8.nobom
Run Code Online (Sandbox Code Playgroud)

要检查BOM:

hd -n 3 UTF8
Run Code Online (Sandbox Code Playgroud)

如果BOM存在,您将看到: 00000000 ef bb bf ...

  • @KarolyHorvath我的意思是*打破**很多程序*.这不是我说的吗?当您以UTF-16或UTF-32编码打开流时,解码器知道不计算BOM.使用UTF-8时,解码器将BOM显示为数据.这是无数程序中的语法错误.[甚至Java的解码器都是这样的,BY DESIGN!](http://bugs.sun.com/view_bug.do?bug_id=4508058)UTF-8文件上的BOM错误放置并且屁股很痛苦:**它们是错误!**他们打破了很多东西.即使只是`cat file1.utf8 file2.utf8 file3.utf3> allfiles.utf8`也会被破坏.切勿在UTF-8上使用BOM.期. (6认同)
  • 对于UTF-16,BOM为2个字节,对于UTF-32为4个字节,当然首先没有UTF-8业务. (5认同)
  • OS X上没有`hd`(从10.8.2开始),所以要检查UTF-8 BOM,可以使用以下命令:`head -c 3 file | od -t x1` (5认同)
  • @KarolyHorvath是的,确切地说.不推荐使用它.它打破了东西.编码应由更高级别的协议指定. (2认同)

Lri*_*Lri 20

除了将CRLF线路结尾转换为LF之外,dos2unix还可以删除BOM:

dos2unix *.txt
Run Code Online (Sandbox Code Playgroud)

dos2unix 还将带有BOM(但不是没有BOM的UTF-16文件)的UTF-16文件转换为UTF-8而不使用BOM:

$ 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
Run Code Online (Sandbox Code Playgroud)