在windows环境下做开发,由于开发者使用的编辑器的不同,可能有部分源码文件带有bom,如果只在Windows环境下开发还好,打算把代码移植到Linux环境就会遇到麻烦。以C++项目为例,这里用perl写一个脚本,遍历文件夹中的所有代码文件,移除bom头部。如果要处理文件夹中的所有文件,或者有其他特定需求,可以自行修改一下正则表达式(代码中有注释标记)。
#! /usr/bin/perl
use v5.14;
use File::Find;
use IO::File;
sub getFileContent {
my $fileName = shift;
my $handle = IO::File->new($fileName, 'r');
$handle->read(my $buffer, -s $handle);
return $buffer;
}
sub hasBom {
my $fileName = shift;
my $content = getFileContent($fileName);
my $bomData = pack('H*', 'EFBBBF');
if ($bomData eq substr($content, 0, 3)) {
return 1;
} else {
return 0;
}
}
sub removeBom {
my $fileName = shift;
return unless hasBom($fileName);
my $content = getFileContent($fileName);
my $handle = IO::File->new($fileName, 'w');
$handle->write(substr($content, 3)) if defined $handle;
}
sub addBom {
my $fileName = shift;
return if hasBom($fileName);
my $bomData = pack('H*', 'EFBBBF');
my $content = getFileContent($fileName);
my $handle = IO::File->new($fileName, 'w');
$handle->write($bomData . $content) if defined $handle;
}
my @filesArry = ();
my $callback = sub {
push @filesArry, $File::Find::name if m{\.(h|hpp|c|cpp|cc)$};
# 如果要处理文件夹中的所有代码,用下面的语句
#push @filesArry, $File::Find::name;
};
if (@ARGV) {
find($callback, $ARGV[0]) if -d $ARGV[0];
} else {
find($callback, './');
}
for my $filePath (@filesArry) {
# 测试添加bom
#addBom($filePath);
if (hasBom($filePath)) {
removeBom($filePath);
say "[REMOVE BOM]: $filePath";
}
}
脚本可以在Windows环境下的git bash执行或者在ubuntu执行, 默认处理的是当前目录,可以额外给脚本传递一个文件夹路径参数。