AWK with BOM:是否有任何很酷的方法可以使用正则表达式处理 Unicode BOM?

AWK with BOM:是否有任何很酷的方法可以使用正则表达式处理 Unicode BOM?

我有两个以 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

两个文件之间的唯一区别是标头 BOM EF BB BF

然后,为了过滤以“a”开头的行,我使用插入符号编写了一个简短的 awk 脚本。

/tmp/bom$ gawk '/^a.*/' list.nobom.txt
apple
avocado
/tmp/bom$ gawk '/^a.*/' list.bom.txt
avocado

不幸的是,对于 header BOM,apple第一行被忽略。

因此,我的问题是:有什么办法可以处理这个问题吗?

我考虑三种解决方案:

  1. 直接写入BOM字节。例如,

    gawk 'BEGIN { pat = "^(\xef\xbb\xbf)?a.*" } $0 ~ pat { print }'
    

    以 UTF-8 工作。但是,这不处理其他编码。此外,如果有 U+FEFF 用作零宽度非中断空间(请参阅注释),则上述脚本在某些情况下会失败。

  2. 通过使用 重新编码来删除 BOM 字节nkf。例如,

    nkf --oc=UTF-8 list.bom.txt | gawk '/^a.*/'
    

    作品。不过我想知道是否有更复杂的方法。

  3. [添加] 这是第一个的改进,使用 bash 功能。

    gawk -v bom="$(echo -e '\uFEFF')" '
        NR == 1 {
            pat = "^" bom;
            sub(pat, "")
        }
        /^a.*/ {
            print
        }
    '
    

    这适用于带/不带 BOM 的 UTF-8。然而,这在我的环境中不适用于 UTF-16。所以,第二种方案更好。

grep而且,我认为这也是使用正则表达式匹配的、sed或其他脚本的问题。因此,如果有一个通用的解决方案,那就更感激了。

答案1

BOM 在 UTF-8 中没有意义。这些通常是由 Microsoft 操作系统上的虚假软件错误添加的。

dos2unix将删除它并处理 Windows 文本文件的其他特性。

dos2unix < file.win.txt | awk ...

相关内容