如何在 UTF-8 语言环境中对 UTF-16LE 文件进行正则表达式搜索?

如何在 UTF-8 语言环境中对 UTF-16LE 文件进行正则表达式搜索?

编辑:由于评论沃伦·杨做出来,这让我意识到我在一个非常相关的观点上并不清楚。我的搜索字符串已经是 UTF-16LE 顺序(不是 Unicode 代码点顺序,即 UTF-16BE),所以也许 Unicode 问题有点没有实际意义,

也许我的问题是如何 grep 组中的字节(而不是字符)2字节, IE。这样UTF-16LE\x09\x0A就不会被视为TAB、换行符,而是被视为恰好是UTF-16LE的2个字节? ...注意:我不需要关心 UTF-16 代理对,所以 2 字节块就可以了。

以下是此 3 字符字符串的示例模式ऊपर

  • \x09\x0A\x09\x2A\x09\x30

    但它什么也不返回,尽管该字符串位于文件中。

(这里是原帖)
在使用 format 模式搜索 UTF-16LE 文件时\x00\x01\x...etc,我遇到了某些值的问题。我一直在使用sed(并尝试过grep),但在 UTF-8 语言环境中,它们将某些 UTF-16LE 值识别为 ASCII 字符。我已锁定使用 UTF-16,因此无法重新编码为 UTF-8。

例如。在此文本(UNICODE 090A) 中,虽然它是单个字符,但被视为两个 ASCII 字符\x09\x0A

grep有一个-P(perl) 选项可以搜索\x00\x...模式,但我得到了相同的 ASCII 解释。

有没有某种方法可以用来grep -P在 UTF-16 模式下进行搜索,或者也许更好,如何通过 perl 或其他脚本来完成此操作。

grep由于其紧凑性,它似乎是最吸引人的,但无论完成什么工作,都会推翻这种偏好。

附注;我的示例使用文字字符串,但我的实际使用需要正则表达式样式搜索。所以这个 Perl 示例不完全是我想要的,尽管它确实将文件处理为 UTF-16...我宁愿不必打开和关闭文件...我认为perl对于诸如正则表达式之类的基本事物有更紧凑的方法搜索。我正在寻找具有这种紧凑语法的东西。

答案1

我的答案基本上与你关于这个话题的其他问题:

$ iconv -f UTF-16LE -t UTF-8 myfile.txt | grep pattern

与另一个问题一样,您可能还需要行结束转换,但重点是您应该将文件转换为本地编码,以便可以直接使用本机工具。

答案2

安装ripgrep公用事业支持UTF-16。

例如:

rg pattern filename

ripgrep 支持以 UTF-8 以外的文本编码搜索文件,例如 UTF-16、latin-1、GBK、EUC-JP、Shift_JIS 等。 (提供了一些对自动检测 UTF-16 的支持。其他文本编码必须用 / 特别-E指定--encoding flag.)

要打印所有行,请运行:rg -N . filename

答案3

我相信沃伦的答案更好一般的*nix 解决方案,但是这个 perl 脚本完全按照我想要的方式工作(对于我有些不标准的情况)。它确实需要我稍微更改搜索模式的当前格式:
\x09\x0A\x09\x2A\x09\x30\x00\s09
     到\x{090A}\x{092A}\x{0930}\x{0009}

它在一个过程中完成所有事情,这正是我所追求的。

#! /usr/bin/env perl
use strict;
use warnings;
die "3 args are required" if scalar @ARGV != 3;
my $if =$ARGV[0];
my $of =$ARGV[1];
my $pat=$ARGV[2];
open(my $ifh, '<:encoding(UTF-16LE)', $if) or warn "Can't open $if: $!";
open(my $ofh, '>:encoding(UTF-16LE)', $of) or warn "Can't open $of: $!";
while (<$ifh>) { print $ofh $_ if /^$pat/; }

答案4

乌格勒普(通用 grep)支持 Unicode、UTF-8/16/32 文件,检测无效的 Unicode 以确保正确的结果,显示文本和二进制文件,并且快速且免费:

乌格勒普搜索 UTF-8/16/32 输入和其他格式。选项 -Q 允许搜索许多其他文件格式,例如 ISO-8859-1 到 16、EBCDIC、代码页 437、850、858、1250 到 1258、MacRoman 和 KOI8。

只需给它一个 Unicode 字符模式来匹配:

ugrep -QUTF-16LE "ऊपर" filename

或使用十六进制代码点:

ugrep -QUTF-16LE "\x{090A}\x{092A}\x{0930}" filename

GitHub 上的 ugrep了解详情。

相关内容