nek*_*uuu 7 awk regular-expression unicode
我有两个文件以 UTF-8 编码,带/不带 BOM:
/tmp/bom$ ls
list.bom.txt list.nobom.txt
/tmp/bom$ cat list.nobom.txt
apple
banana
avocado
??
melon
/tmp/bom$ diff list.nobom.txt list.bom.txt
1c1
< apple
---
> apple
/tmp/bom$ file list.nobom.txt list.bom.txt
list.nobom.txt: UTF-8 Unicode text
list.bom.txt: UTF-8 Unicode (with BOM) text
Run Code Online (Sandbox Code Playgroud)
两个文件之间的唯一区别是标题 BOM EF BB BF
。
然后,为了过滤以 'a' 开头的行,我使用插入符号编写了一个简短的 awk 脚本。
/tmp/bom$ gawk '/^a.*/' list.nobom.txt
apple
avocado
/tmp/bom$ gawk '/^a.*/' list.bom.txt
avocado
Run Code Online (Sandbox Code Playgroud)
不幸的是,对于标题 BOM,apple
在第一行中被忽略了。
因此,我的问题是:有没有办法处理这个问题?
我考虑了三种解决方案:
直接写入 BOM 字节。例如,
gawk 'BEGIN { pat = "^(\xef\xbb\xbf)?a.*" } $0 ~ pat { print }'
Run Code Online (Sandbox Code Playgroud)
在 UTF-8 中工作。但是,这不处理其他编码。此外,如果将 U+FEFF 用作零宽度非中断空间(请参阅注释),则上述脚本在某些情况下会失败。
通过重新编码来删除 BOM 字节nkf
。例如,
nkf --oc=UTF-8 list.bom.txt | gawk '/^a.*/'
Run Code Online (Sandbox Code Playgroud)
作品。但是,我想知道是否有更复杂的方法。
[添加] 这是第一个的改进,使用 bash 功能。
gawk -v bom="$(echo -e '\uFEFF')" '
NR == 1 {
pat = "^" bom;
sub(pat, "")
}
/^a.*/ {
print
}
'
Run Code Online (Sandbox Code Playgroud)
这适用于带/不带 BOM 的 UTF-8。但是,这不适用于我的环境中的 UTF-16。所以,第二种解决方案更好。
此外,我想这也是这个问题grep
,sed
使用正则表达式匹配,或其他脚本。所以,如果有一个通用的解决方案,它会更受欢迎。
BOM 在 UTF-8 中没有意义。这些通常是由 Microsoft 操作系统上的虚假软件错误添加的。
dos2unix
将删除它并处理 Windows 文本文件的其他特性。
dos2unix < file.win.txt | awk ...
Run Code Online (Sandbox Code Playgroud)