Linux下utf-8 BOM 文件的检查与删除

当源程序是 gbk 格式,你转换为 utf8 的时候,很多情况是头部会出现 bom,如果是 php 代码,这样会出现很多意想不到的事情,那怎么办呢,你可以用 linux 命令来查找,然后对文件的 bom 进行删除。

grep -r $'\xef\xbb\xbf' * |grep .php

bom:UTF-8签名(UTF-8 signature)也叫做BOM(Byte Order Mark)

查询BOM:

:set bomb?

用 vim 去掉 utf-8 BOM

:set nobomb

保留 utf-8 BOM

:set bomb

vim 转换文件为 unix 格式

:set ff=unix

使用 grep 查找带 bom 的文件,并使用 perl 去掉 bom 头

grep -rl $'\xEF\xBB\xBF' . | xargs perl -i -pe 's{\xEF\xBB\xBF}{}'

About字符编码

打开”记事本”程序Notepad.exe,新建一个文本文件,内容就是一个”严”字,依次采用ANSI,Unicode,Unicode big endian 和 UTF-8编码方式保存。

然后,用文本编辑软件UltraEdit中的”十六进制功能”,观察该文件的内部编码方式。

1)ANSI:文件的编码就是两个字节”D1 CF”,这正是”严”的GB2312编码,这也暗示GB2312是采用大头方式存储的。

2)Unicode:编码是四个字节”FF FE 25 4E”,其中”FF FE”表明是小头方式存储,真正的编码是4E25。

3)Unicode big endian:编码是四个字节”FE FF 4E 25″,其中”FE FF”表明是大头方式存储。

4)UTF-8:编码是六个字节”EF BB BF E4 B8 A5″,前三个字节”EF BB BF”表示这是UTF-8编码,后三个”E4B8A5″就是”严”的具体编码,它的存储顺序与编码顺序是一致的。

UTF-8编码的文件中,BOM占三个字节。如果用记事本把一个文本文件另存为UTF-8编码方式的话,用UE打开这个文件,切换到十六进制编辑状态就可以看到开头的FFFE了。这是个标识UTF-8编码文件的好办法,软件通过BOM来识别这个文件是否是UTF-8编码,很多软件还要求读入的文件必须带BOM。可是,还是有很多软件不能识别BOM。

PHP在设计时就没有考虑BOM的问题,也就是说他不会忽略UTF-8编码的文件开头BOM的那三个字符。

由于必须在在Bo-Blog的wiki看到,同样使用PHP的Bo-Blog也一样受到BOM的困扰。其中有提到另一个麻烦:“受COOKIE送出机制的限制,在这些文件开头已经有BOM的文件中,COOKIE无法送出(因为在COOKIE送出前PHP已经送出了文件头),所以登入和登出功能失效。一切依赖COOKIE、SESSION实现的功能全部无效。”这个应该就是Wordpress后台出现空白页面的原因了,因为任何一个被执行的文件包含了BOM,这三个字符都将被送出,导致依赖cookies和session的功能失效。

解决的办法嘛,如果只包含英文字符(或者说ASCII编码内的字符),就把文件存成ASCII码方式吧。用UE等编辑器的话,点文件->转换->UTF-8转ASCII,或者在另存为里选择ASCII编码。如果是DOS格式的行尾符,可以用记事本打开,点另存为,选ASCII编码。如果包含中文字符的话,可以用UE的另存为功能,选择“UTF-8 无 BOM”即可。

当然在Python程序中处理的时候遇到这种情况改怎么处理呢?

方法一:直接将源文件的格式修改一下,将其保存为UTF-8即可,但是很多时候传过来的源文件是没法修改的,这样就行不通了。

方法二:替换,就是将其中的\xef\xbb\xbf替换为空就可以了。

VIM 十六进制和文本模式切换

使用vim打开文件后,使用命令

:%!xxd 使用十六进制显示;
:%!xxd -r 返回文本显示。

只有十六进制部分的修改才会被采用。右边可打印文本部分的修改忽略不计。

vim以二进制打开文件

vim -b binfile

在 Vim 中将文件保为无 BOM 的 UTF-8 格式

查看文件格式

通常我们需要先查看文件格式是否与预期的一样,再根据结果决定是否需要修改(当然你也可以在不知道原格式的情况下直接修改),下面分别给出了查看文件编码和是否带有 BOM 的命令。

# 查看文件编码。
set fenc?
# 查看是否带 BOM。
set bomb?

修改文件格式

# 设置为 UTF-8 编码。
set fenc=utf-8
# 设置为无 BOM,如需设置为带 BOM 则使用 "set bomb"。
set nobomb
# 加上BOM标记
set bomb

使用linux命令删除UTF-8编码中的BOM

shell> grep -r -I -l $'^\xEF\xBB\xBF' /path | xargs sed -i 's/^\xEF\xBB\xBF//;q'
or
shell> grep -r -I -l $'^\xEF\xBB\xBF' /path | xargs sed -i 's/^\xEF\xBB\xBF//g'
or
shell> tail -c +4 old_file > new_file

如果使用SVN提交代码的话,可以在pre-commit钩子里加上相关代码用以杜绝BOM。

#!/bin/bash

REPOS="$1"
TXN="$2"

SVNLOOK=/usr/bin/svnlook

for FILE in $($SVNLOOK changed -t "$TXN" "$REPOS" | awk '/^[AU]/ {print $NF}'); do
    if $SVNLOOK cat -t "$TXN" "$REPOS" "$FILE" | grep -q $'^\xEF\xBB\xBF'; then
        echo "Byte Order Mark be found in $FILE" 1>&2
        exit 1
    fi
done

不含 BOM 的 UTF-8 才是标准形式!
带 BOM 的 UTF-8 就是赤裸裸的流氓!!!

 

不同编码的BOM表示

编码 十六进制表示
UTF-8 EF BB BF
UTF-16-BE FE FF
UTF-16-LE FF FE
UTF-32-BE 00 00 FE FF
UTF-32-LE FF FE 00 00
UTF-7 2B 2F 76和以下的一个字节:[ 38 39 2B 2F ]
en:UTF-1 F7 64 4C
en:UTF-EBCIC DD 73 66 73
en:Standard Compression Scheme for Unicode 0E FE FF
en:BOCU-1 FB EE 28及可能跟随着FF
GB-18030 84 31 95 33

vim 将文件从dos格式转换到unix格式

:set fileformat=unix
:w

vim 将文件从unix格式转换到dos格式

:set fileformat=dos
:w

VIM 状态栏显示 文件格式带bom
Show fileencoding and bomb in the status line
http://vim.wikia.com/wiki/Show_fileencoding_and_bomb_in_the_status_line
比如 [latin1], [iso-8859-15], [utf-8,B], etc.

if has("statusline")
 set statusline=%<%f\ %h%m%r%=%{\"[\".(&fenc==\"\"?&enc:&fenc).((exists(\"+bomb\")\ &&\ &bomb)?\",B\":\"\").\"]\ \"}%k\ %-14.(%l,%c%V%)\ %P
endif

其实有用的就是这段:

%{\"[\".(&fenc==\"\"?&enc:&fenc).((exists(\"+bomb\")\ &&\ &bomb)?\",B\":\"\").\"]\ \"}

Debian6 编译安装vim 7.4

一、安装VIM7.4之前的准备工作

apt-get update

遇到问题:
W: 以下 ID 的密钥没有可用的公钥:
8B48AD6246925553

解决方法:

gpg --keyserver subkeys.pgp.net --recv 8B48AD6246925553
gpg --export --armor 8B48AD6246925553 | sudo apt-key add -

继续执行 apt-get update
完成后安装VIM的依赖库环境

apt-get install libncurses5-dev libgnome2-dev libgnomeui-dev libgtk2.0-dev \
libatk1.0-dev libbonoboui2-dev libcairo2-dev libx11-dev libxpm-dev libxt-dev \
python-dev libperl-dev ruby-dev liblua5.1-0-dev

二、卸载老版本vim

apt-get remove vim vim-runtime gvim

三、编译新版本vim

cd /usr/src/
wget ftp://ftp.vim.org/pub/vim/unix/vim-7.4.tar.bz2
tar jxvf vim-7.4.tar.bz2
./configure --prefix=/usr/local/vim74 \
--with-features=huge \
--enable-pythoninterp --enable-perlinterp \
--enable-rubyinterp --enable-luainterp \
--enable-multibyte --enable-sniff --enable-fontset
--with-features=huge:支持最大特性
--enable-pythoninterp:启用Vim对python的支持
--enable-perlinterp:启用Vim对perl的支持
--enable-rubyinterp:启用Vim对ruby的支持
--enable-luainterp:启用Vim对lua的支持
--enable-multibyte:多字节支持 可以在Vim中输入中文
--enable-sniff:Vim状态提示 提示Vim当前处于INSERT、NORMAL、VISUAL哪种模式
--enable-cscope:Vim对cscope支持
 更多参数执行./configure --help查看

编译和安装

make && make instal

四、链接以便识别vim命令

ln -s /usr/local/vim74/bin/vim /usr/bin/vim
ln -s /usr/local/vim74/bin/gvim /usr/bin/gvim

五、把vim作为默认编辑器

sudo update-alternatives --install /usr/bin/editor editor /usr/bin/vim 1
sudo update-alternatives --set editor /usr/bin/vim
sudo update-alternatives --install /usr/bin/vi vi /usr/bin/vim 1
sudo update-alternatives --set vi /usr/bin/vim

FreeBSD 8.1上安装Vim

1、安装 axel 优化 ports 速度

FreeBSD 中的 ports 安装工具默认下载程序用的是 fetch,下载时经常会出现龟速现象,为了提高 ports 安装速度,推荐替换为 axel 或者 wget,当然具体还得配置下 make.conf 文件。

1.1 使用 ports 安装 axel

cd /usr/ports/ftp/axel
make install

1.2 编辑make.conf配置文件

vi /etc/make.conf # 系统缺省安装以后没有 /etc/make.conf,自己创建一个。####加入以下内容####

FETCH_CMD = axel
FETCH_BEFORE_ARGS = -n 10 -a
FETCH_AFTER_ARGS =
DISABLE_SIZE = yes

MASTER_SITE_BACKUP?=\
http://mirrors.ustc.edu.cn/freebsd-ports/distfiles/${DIST_SUBDIR}/ \
ftp://ftp.cn.freebsd.org/pub/FreeBSD/distfiles/${DIST_SUBDIR}/
MASTER_SITE_OVERRIDE?=${MASTER_SITE_BACKUP}

“?=” 表示如果没有赋值过,就赋值等号后面的值。

Assign the value to the variable if it is not already defined. 如果尚未定义该值,则将其分配给该变量。

参考 https://man.openbsd.org/make#VARIABLE_ASSIGNMENTS

Makefile一共提供了四个赋值运算符 (=、:=、?=、+=),它们的区别请看StackOverflow

1.3 portsnap 常用参数有以下三个

fetch 获取数据
extract 释放全部 ports
update 更新 ports

使用 portsnap 分成两个步骤:

下载压缩的 portsnap 快照,和更新现有系统。

下载或更新 portsnap 快照的方法是 portsnap fetch;首次安装,或希望将 ports tree 恢复到快照的样子,应使用 portsnap extract;之后更新系统中的 ports tree,则可以通过 portsnap update 来完成。

对于服务器而言,推荐在 crontab 中增加在每天3点执行 portsnap cron,以减少使用时所需要的下载时间。

首次下载 portsnap 快照时,需要下载一个大约50MB的快照基础文件。在中国大陆,由于网络状况的原因,这可能需要较长时间。可以考虑用 portsnap fetch -s portsnap.cn.freebsd.org 做首次下载。之后的下载,还是推荐使用正常的 portsnap fetch。

可以使用下面步骤完成上述情况

1.首先设置一个比较快的portsnap服务器,如果系统默认的地址你的访问速度也很快,可以不修改

vi /etc/portsnap.conf

设置SERVERNAME=portsnap.cn.freebsd.org ,你可以设置相对你速度快点的服务器的地址

2.执行下面命令

portsnap fetch extract

这样就完成了下载ports系统以及解压到/usr下面了,以后就不用 extract 了,用 update 更新。

portsnap fetch update

portsnap 第一次运行 extract 命令时,可能需要一段时间,以后更新使用 update 的时候,速度就快很多了。

如果写在 cron 可以用

portsnap cron update

这样定时更新就不用你要安装软件的时候更新了,节省时间。

2、安装 Vim

查找 vim 在 ports 的路径,这个好像在 Port 里边有个数据库树,存储各种软件的所在位置。

查找 vim 在 ports 的哪个目录位置

whereis vim
#或
cd /usr/ports/
make search name=vim
cd /usr/ports/editors/vim
make -DWITHOUT_X11 install clean
or
make WITHOUT_X11=yes install clean

-DWITHOUT_X11 选项作用是:不安装图形化界面的依赖包,只安装字符界面相关的包,这样子速度很快,我是用默认安装的 Ports 可能下载源也慢,肯能大概安装了4个小时很纳闷,后来终于发现添加 -DWINTOUT_X11 选项后 一会就安装好了。 PS:为啥我的还这么慢呢,都刷了20分钟了。

下载 vim patches 文件:
这里批量下载命令:从 北京理工大学开源软件镜像服务 当中下载:

rsync -vaHz --delete rsync://mirror.bit.edu.cn/pub/vim/patches/ ./

然后把这些文件 cp 到 /usr/ports/disfile/vim 目录中。

3、用 portmaster的方式安装

cd /usr/ports/
portmaster -GD --no-confirm editors/vim-console

-G //阻止make config,也就是使用默认选项
-D 升級或移除ports的時候不要將用不到的distfiles砍掉
--no-confirm //在将要执行升级或者安装之前,不询问用户,直接执行

PS:不使用图形界面的建议安装 vim-console,而非 vim,用 ports 安装 vim 默认是带 X 支持的,会附带安装上很多的 X 支持包。

VIM 配置:

root@JavasBoy.pts/0 ~ # cat .vimrc
set encoding=utf-8
set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1
set noswapfile                  " Don't use swapfile
set nobackup                    " Don't create annoying backup files
set number
set cindent

" TAB setting
set expandtab               " replace  with spaces
"set noexpandtab				" 不自动把table转换为空格
set tabstop=4
set softtabstop=4
set shiftwidth=4
autocmd FileType yaml set expandtab

set nocompatible            " 设定 gvim 运行在增强模式下
set backspace=indent,eol,start
                            " 不设定的话在插入状态无法用退格键和 Delete
                            " 键删除回车符

set autoindent
set ruler
" Colorscheme
syntax on
set t_Co=256

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 
" 设置命令行和状态栏
 
set cmdheight=1             " 设定命令行的行数为 1
set laststatus=2            " 显示状态栏 (默认值为 1, 无法显示状态栏)
set statusline=%F%m%r\ \|\ %{&ff},%{\"[\".(&fenc==\"\"?&enc:&fenc).((exists(\"+bomb\")\ &&\ &bomb)?\",B\":\"\").\"]\ \"},%Y\ \|%=\ %l/%L,%c\ \|\ %f
                            " 设置在状态行显示的信息如下:
                            " %f    当前的文件名
                            " %F    当前全路径文件名
                            " %m    当前文件修改状态
                            " %r    当前文件是否只读
                            " %Y    当前文件类型
                            " %{&fileformat}
                            "       当前文件编码
                            " %{&fileencoding}
                            "       中文编码
                            " %b    当前光标处字符的 ASCII 码值
                            " %B    当前光标处字符的十六进制值
                            " %l    当前光标行号
                            " %c    当前光标列号
                            " %V    当前光标虚拟列号 (根据字符所占字节数计算)
                            " %p    当前行占总行数的百分比
                            " %%    百分号
                            " %L    当前文件总行数
 
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 
" 显示空白字符
"set listchars=eol:¬,tab:>·,trail:~,extends:>,precedes:<,space:␣
set listchars=eol:¬,tab:»·,trail:~,extends:>,precedes:<,space:␣

FreeBSD下的Vim默认安装路径为

/usr/local/share/vim/vim7*

在 FreeBSD 10.0 中 VIM 全局配置文件是放在

/usr/local/share/vim/vimrc

vim 7.4.900 vimrc localtion is

/usr/local/etc/vim/vimrc

这个文件中,每个用户的配置文件就是在~/.vimrc,一般我喜欢设置全局的。

让你在 FreeBSD 下用的更顺手。
https://wiki.freebsdchina.org/howto/c/config_your_csh

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 
" 设置命令行和状态栏
 
set cmdheight=1             " 设定命令行的行数为 1
set laststatus=2            " 显示状态栏 (默认值为 1, 无法显示状态栏)
set statusline=%F%m%r\ \|\ %{&ff},%{\"[\".(&fenc==\"\"?&enc:&fenc).((exists(\"+bomb\")\ &&\ &bomb)?\",B\":\"\").\"]\ \"},%Y\ \|%=\ %l/%L,%c\ \|\ %f
                            " 设置在状态行显示的信息如下:
                            " %f    当前的文件名
                            " %F    当前全路径文件名
                            " %m    当前文件修改状态
                            " %r    当前文件是否只读
                            " %Y    当前文件类型
                            " %{&fileformat}
                            "       当前文件编码
                            " %{&fileencoding}
                            "       中文编码
                            " %b    当前光标处字符的 ASCII 码值
                            " %B    当前光标处字符的十六进制值
                            " %l    当前光标行号
                            " %c    当前光标列号
                            " %V    当前光标虚拟列号 (根据字符所占字节数计算)
                            " %p    当前行占总行数的百分比
                            " %%    百分号
                            " %L    当前文件总行数
 
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 
" 显示空白字符
set listchars=eol:¬,tab:>·,trail:~,extends:>,precedes:<,space:␣

vim切换tab标签快捷键

这几天在学习VIM,在WIN7下装了GVIM,在折腾好配置文件后,就在弄这个
切换标签快捷键的问题。
vim从vim7开始加入了多标签切换的功能,相当于多窗口。
之前的版本虽然也有多文件编辑功能,但是总之不如这个方便啦。
用法

:tabnew [++opt选项] [+cmd] 文件            建立对指定文件新的tab
:tabc       关闭当前的tab
:tabo       关闭所有其他的tab
:tabs       查看所有打开的tab
:tabp      前一个
:tabn      后一个
标准模式下:
gt , gT 可以直接在tab之间切换。
更多可以查看帮助 :help table , help -p

使用alt+数字键来切换tab (vim7+)

不过用gt,gT来一个个切换有点不方便, 如果用:tabnext {count}, 又按键太多. 加入以下代码后, 可以用 alt+n来切换,
比如alt+1切换到第一个tab,alt+2切换到第二个tab。

把以下代码加到vimrc, 或者存为.vim文件,再放到plugin目。

function! TabPos_ActivateBuffer(num)
    let s:count = a:num
    exe "tabfirst"
    exe "tabnext" s:count
endfunction

function! TabPos_Initialize()
for i in range(1, 9)
        exe "map <M-" . i . "> :call TabPos_ActivateBuffer(" . i . ")<cr>"
    endfor
    exe "map <M-0> :call TabPos_ActivateBuffer(10)</cr><cr>"
endfunction

autocmd VimEnter * call TabPos_Initialize()

上面的看上去太复杂了,来个简单的。

:nn <M-1> 1gt
:nn <M-2> 2gt
:nn <M-3> 3gt
:nn <M-4> 4gt
:nn <M-5> 5gt
:nn <M-6> 6gt
:nn <M-7> 7gt
:nn <M-8> 8gt
:nn <M-9> 9gt
:nn <M-0> :tablast</cr><cr>

把这个放进_vimrc配置文件里。
继续阅读“vim切换tab标签快捷键”