如何在vim中搜索所有的CJK字符?

8
我可以通过使用Unicode码点来搜索CJK字符(例如):
/\%u5c0f
/[\u5c0f]

我无法使用[\u4E00-\u9FFF]搜索所有的CJK字符,因为vim手册中提到:

:help /[]
注意:上述其他反斜杠代码在[]内不起作用!

有没有办法完成这项工作?


如果您只搜索特定的CJK字符,可以直接在搜索框中输入该字符。例如:/小 - David.Chu.ca
5个回答

4

看起来 Vim 的范围在某种程度上受到了同一高位字节的限制,因为 /[\u4E00-\u4eFF] 是可以正常工作的。如果您不介意混乱,请尝试:

/[\u4e00-\u4eff\u4f00-\u4fff\u5000-\u50ff\u5100-\u51ff\u5200-\u52ff\u5300-\u53ff\u5400-\u54ff\u5500-\u55ff\u5600-\u56ff\u5700-\u57ff\u5800-\u58ff\u5900-\u59ff\u5a00-\u5aff\u5b00-\u5bff\u5c00-\u5cff\u5d00-\u5dff\u5e00-\u5eff\u5f00-\u5fff\u6000-\u60ff\u6100-\u61ff\u6200-\u62ff\u6300-\u63ff\u6400-\u64ff\u6500-\u65ff\u6600-\u66ff\u6700-\u67ff\u6800-\u68ff\u6900-\u69ff\u6a00-\u6aff\u6b00-\u6bff\u6c00-\u6cff\u6d00-\u6dff\u6e00-\u6eff\u6f00-\u6fff\u7000-\u70ff\u7100-\u71ff\u7200-\u72ff\u7300-\u73ff\u7400-\u74ff\u7500-\u75ff\u7600-\u76ff\u7700-\u77ff\u7800-\u78ff\u7900-\u79ff\u7a00-\u7aff\u7b00-\u7bff\u7c00-\u7cff\u7d00-\u7dff\u7e00-\u7eff\u7f00-\u7fff\u8000-\u80ff\u8100-\u81ff\u8200-\u82ff\u8300-\u83ff\u8400-\u84ff\u8500-\u85ff\u8600-\u86ff\u8700-\u87ff\u8800-\u88ff\u8900-\u89ff\u8a00-\u8aff\u8b00-\u8bff\u8c00-\u8cff\u8d00-\u8dff\u8e00-\u8eff\u8f00-\u8fff\u9000-\u90ff\u9100-\u91ff\u9200-\u92ff\u9300-\u93ff\u9400-\u94ff\u9500-\u95ff\u9600-\u96ff\u9700-\u97ff\u9800-\u98ff\u9900-\u99ff\u9a00-\u9aff\u9b00-\u9bff\u9c00-\u9cff\u9d00-\u9dff\u9e00-\u9eff\u9f00-\u9fff]

当我搜索这个模式时,Vim会冻结。但是它仍然有效。再次感谢! - kev
1
@kev 是的,在帮助文件中有解释:当您使用集合时,要检查匹配的字符将与集合中的所有字符进行比较。它不会检查是否在某个范围内。因此,上面的正则表达式对于每个字符执行了20910次检查。当然,vim会冻结。 - ZyX

3

我经过一番尝试,在vim中发现以下命令能够找到所有汉字字符:

[^!-~0-9 aāáǎăàeēéěèiīíǐĭìoōóǒŏòuūúǔùǖǘǚǜ]

2

Vim本身无法实现此功能,因为您无法访问Unicode属性,例如\p{Han}

截至Unicode v6.0,汉字字符的代码点范围为:

2E80-2E99 2E9B-2EF3 2F00-2FD5 3005-3005 3007-3007 3021-3029 3038-303B 3400-4DB5 4E00-9FCB F900-FA2D FA30-FA6D FA70-FAD9 20000-2A6D6 2A700-2B734 2B740-2B81D 2F800-2FA1D 

随着Unicode v6.1的发布,汉字编码范围已经发生了变化:

2E80-2E99 2E9B-2EF3 2F00-2FD5 3005-3005 3007-3007 3021-3029 3038-303B 3400-4DB5 4E00-9FCC F900-FA6D FA70-FAD9 20000-2A6D6 2A700-2B734 2B740-2B81D 2F800-2FA1D 

我还记得Vim在表达astral码点时存在困难,而这对于正确运行是必需的。例如,使用Java 7或Perl中灵活的\x{HHHHHH}表示法,您可以这样写:

[\x{2E80}-\x{2E99}\x{2E9B}-\x{2EF3}\x{2F00}-\x{2FD5}\x{3005}-\x{3005}\x{3007}-\x{3007}\x{3021}-\x{3029}\x{3038}-\x{303B}\x{3400}-\x{4DB5}\x{4E00}-\x{9FCC}\x{F900}-\x{FA6D}\x{FA70}-\x{FAD9}\x{20000}-\x{2A6D6}\x{2A700}-\x{2B734}\x{2B740}-\x{2B81D}\x{2F800}-\x{2FA1D}]

注意,范围的最后一部分是\x{2F800}-\x{2FA1D},这已经超出了BMP。但你真正需要的是\p{Han}(意思是\p{Script=Han})。这再次表明,不支持至少UTS#18基本Unicode支持级别1的正则表达式方言对于处理Unicode是不充分的。Vim的正则表达式在处理基本的Unicode工作方面也是不充分的。


编辑添加

下面是一个程序,它会输出适用于任何给定Unicode脚本的码点范围。

#!/usr/bin/env perl
#
# uniscrange - given a Unicode script name, print out the ranges of code 
#              points that apply.
# Tom Christiansen <tchrist@perl.com>

use strict;
use warnings;

use Unicode::UCD qw(charscript);

for my $arg (@ARGV) {
    print "$arg: " if @ARGV > 1;
    dump_range($arg);
}

sub dump_range {
    my($scriptname) = @_;

    my $alist = charscript($scriptname);
    unless ($alist) {
        warn "Unknown script '$scriptname'\n";
        return;
    }

    for my $aref (@$alist) {
        my($start, $stop, $name) = @$aref;
        die "got $name, not $scriptname\n" unless $name eq $scriptname;
        printf "%04X-%04X ", $start, $stop;
    }
    print "\n";

}

这个问题的答案取决于你使用的Perl版本,因此也取决于你使用的Unicode版本。

$ perl5.8.8 ~/uniscrange Latin Greek
Latin: 0041-005A 0061-007A 00AA-00AA 00BA-00BA 00C0-00D6 00D8-00F6 00F8-01BA 01BB-01BB 01BC-01BF 01C0-01C3 01C4-0241 0250-02AF 02B0-02B8 02E0-02E4 1D00-1D25 1D2C-1D5C 1D62-1D65 1D6B-1D77 1D79-1D9A 1D9B-1DBF 1E00-1E9B 1EA0-1EF9 2071-2071 207F-207F 2090-2094 212A-212B FB00-FB06 FF21-FF3A FF41-FF5A 
Greek: 0374-0375 037A-037A 0384-0385 0386-0386 0388-038A 038C-038C 038E-03A1 03A3-03CE 03D0-03E1 03F0-03F5 03F6-03F6 03F7-03FF 1D26-1D2A 1D5D-1D61 1D66-1D6A 1F00-1F15 1F18-1F1D 1F20-1F45 1F48-1F4D 1F50-1F57 1F59-1F59 1F5B-1F5B 1F5D-1F5D 1F5F-1F7D 1F80-1FB4 1FB6-1FBC 1FBD-1FBD 1FBE-1FBE 1FBF-1FC1 1FC2-1FC4 1FC6-1FCC 1FCD-1FCF 1FD0-1FD3 1FD6-1FDB 1FDD-1FDF 1FE0-1FEC 1FED-1FEF 1FF2-1FF4 1FF6-1FFC 1FFD-1FFE 2126-2126 10140-10174 10175-10178 10179-10189 1018A-1018A 1D200-1D241 1D242-1D244 1D245-1D245

$ perl5.10.0 ~/uniscrange Latin Greek
Latin: 0041-005A 0061-007A 00AA-00AA 00BA-00BA 00C0-00D6 00D8-00F6 00F8-01BA 01BB-01BB 01BC-01BF 01C0-01C3 01C4-0293 0294-0294 0295-02AF 02B0-02B8 02E0-02E4 1D00-1D25 1D2C-1D5C 1D62-1D65 1D6B-1D77 1D79-1D9A 1D9B-1DBE 1E00-1E9B 1EA0-1EF9 2071-2071 207F-207F 2090-2094 212A-212B 2132-2132 214E-214E 2184-2184 2C60-2C6C 2C74-2C77 FB00-FB06 FF21-FF3A FF41-FF5A 
Greek: 0374-0375 037A-037A 037B-037D 0384-0385 0386-0386 0388-038A 038C-038C 038E-03A1 03A3-03CE 03D0-03E1 03F0-03F5 03F6-03F6 03F7-03FF 1D26-1D2A 1D5D-1D61 1D66-1D6A 1DBF-1DBF 1F00-1F15 1F18-1F1D 1F20-1F45 1F48-1F4D 1F50-1F57 1F59-1F59 1F5B-1F5B 1F5D-1F5D 1F5F-1F7D 1F80-1FB4 1FB6-1FBC 1FBD-1FBD 1FBE-1FBE 1FBF-1FC1 1FC2-1FC4 1FC6-1FCC 1FCD-1FCF 1FD0-1FD3 1FD6-1FDB 1FDD-1FDF 1FE0-1FEC 1FED-1FEF 1FF2-1FF4 1FF6-1FFC 1FFD-1FFE 2126-2126 10140-10174 10175-10178 10179-10189 1018A-1018A 1D200-1D241 1D242-1D244 1D245-1D245

您可以使用 corelist -a Unicode 命令来查看 Unicode 的版本与 Perl 版本的对应关系。以下是部分输出结果:
$ corelist -a Unicode
  v5.8.8     4.1.0     
  v5.10.0    5.0.0     
  v5.12.2    5.2.0     
  v5.14.0    6.0.0     
  v5.16.0    6.1.0     

/[\x{2E80}-\x{2E99}] ==> E16:范围无效 - kev
@kev,我明确说明了我正在使用\x{HHHHHH}符号(Vim不理解),这样我就可以指定任意平面中的任意代码点,而不仅仅是BMP中的代码点,因为\uHHHH(Vim理解)只提供了BMP中的代码点。这是必要的,以便理解问题。 - tchrist
@kev Java7同样也使用这种符号表示正则表达式。对于超过BMP的代码点是必要的。请注意,您所接受的答案忽略了\p{Han}中的非BMP范围,根据Unicode v6.1,范围为20000-2A6D6、2A700-2B734、2B740-2B81D和2F800-2FA1D。您需要我编写的生成这些范围的程序吗? - tchrist
@kev 我已经更新了答案,包括显示脚本范围的程序。 - tchrist
请问您能告诉我所有韩文字母的范围吗? - Lerner Zhang

2
在一些简单的情况下,我使用这个来搜索汉字。它还可以匹配日文、俄文等字符。
[^\x00-\xff] 

2

虽然我不理解“同高位字节问题”,但在实际输入字符以建立范围时,似乎并不适用于我(至少对于我而言,VIM 7.4)。

我通常从U+3400(㐀)到U+9FCC(鿌)搜索,以捕获日本文本中的汉字。

  • U+3400(㐀)是“CJK统一表意文字扩展A”的开始
  • U+4DC0-U+4DFF“易经六十四卦符号”介于其间,但出于简单起见未被排除。
  • U+9FCC(鿌)是“CJK统一表意文字”的结尾

请注意,日语书写使用“々”作为重复汉字符号,该符号不属于此块。您可以在块“日语符号和标点符号”中找到它。

/[㐀-鿌]

一个几乎完整的带扩展的中文字符集

/[㐀-鿌豈-龎-]

此范围包括:

  • CJK统一表意文字扩展A
  • 易经六十四卦符号(不应该是其中的一部分)
  • CJK统一表意文字(主要部分)
  • CJK兼容性表意文字
  • CJK统一表意文字扩展B
  • CJK统一表意文字扩展C
  • CJK统一表意文字扩展D
  • CJK兼容性表意文字补充

对于从事日语内容工作的人的奖励:

平假名范围从U+3041到U+3096。

/[ぁ-ゟ]

片假名

/[゠-ヿ]

汉字偏旁部首

/[⺀-⿕]

日本符号和标点。

请注意,此范围还包括々(重复上一个汉字)和〆(shime「しめ」的缩写)。您可能希望将它们添加到您的范围以查找单词。

[ -〿]

杂项日本符号和字符

/[ㇰ-ㇿ㈠-㉃㊀-㍿]

字母数字和标点符号(全角)

[!-~]

sources:

http://www.fileformat.info/info/unicode/char/9fcc/index.htm http://www.localizingjapan.com/blog/2012/01/20/regular-expressions-for-japanese-text/comment-page-1/#comment-46891


非常感谢您提供平假名和片假名。 - whitesiroi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接