【问题标题】:Search for Characters Similar to Special Characters搜索与特殊字符相似的字符
【发布时间】:2016-07-31 17:34:06
【问题描述】:

我有几个旧文本数据文件,这些文件是在 90 年代使用旧的 DOS 时代文字处理器生成的。由于当时存在的限制,在数据输入过程中有很多很多条目被“简化”了。

例如,“Náufragos”一词输入为“Naufragos”。

现在,当在所述数据文件中搜索“Náufragos”时,我使用 grep 查找“Náufragos”并且搜索结果为空(应该如此),但我确实需要所述搜索来查找并输出“Naufragos”。

我已经梳理了 grep 文档并在 Google 上进行了广泛搜索,但结果都是空的。

任何解决方案都需要处理涉及大多数(如果不是全部)字符“变体”的情况,这些“变体”基于基于拉丁字母表(即,在所说的中没有中文、西里尔文、日文等)旧数据文件)。

是否有 grep 或 perl 选项可以做到这一点?可能是这样的:

grep -<magic option> Náufragos file.txt

【问题讨论】:

标签: perl unix search grep special-characters


【解决方案1】:

要忽略变音符号,您可以使用 Unicode 排序算法在级别 1 进行搜索。

#!/usr/bin/perl

use strict;
use warnings;
use Unicode::Collate;

my $collator=Unicode::Collate->new(level => 1, normalization => undef);

while (<>) {
        print if $collator->match($_, "Naufragos")
}

将此脚本命名为ucagrep.pl:

$ echo -e "Náufragos\nNaufragos\nÑaufragos" | perl -CS ucagrep.pl 
Náufragos
Naufragos
Ñaufragos

呃。我们最好指定语言环境:

#!/usr/bin/perl

use strict;
use warnings;
use Unicode::Collate::Locale;

my $collator=Unicode::Collate::Locale->new(locale => "es", level => 1, normalization => undef);

while (<>) {
        print if $collator->match($_, "Naufragos")
}

测试它:

$ echo -e "Náufragos\nNaufragos\nÑaufragos" | perl -CS ucagrep.pl 
Náufragos
Naufragos

好多了。

【讨论】:

    【解决方案2】:

    您始终可以使用字符范围进行 grep,例如,

    grep -i 'N[aá]ufragos' *
    

    要匹配名称的任一拼写,如果这很麻烦,使用Text::Unidecode 的脚本(如How to convert letters with accents, umlauts, etc to their ASCII counterparts in Perl? 中所述)可以 生成范围表达式(因为您可能只处理 ISO-8859-1 中带有变音符号的几十个字符)。

    Text::Unidecode 的一个缺点是它不太可能预先安装在系统上(例如,我看到 Debian 中没有软件包)。您可以直接从 CPAN 获取,例如,使用 cpanminus

    这是一个简单的例子,只是搜索旧名称(cpanminus 将包放在非标准位置):

    #!/usr/bin/perl -w
    
    use strict;
    use lib '/usr/local/lib/perl';
    use Text::Unidecode;
    
    my @args = unidecode(@ARGV);
    
    for my $n ( 0 .. $#args ) {
        my $name = $args[$n];
        printf "** grep %s ->%s\n", $ARGV[$n], $args[$n];
        system("grep -r \"$name\" .");
    }
    
    1;
    

    但是,更好的脚本会同时匹配旧/新名称,因为很容易忽略已转换的文件。是否忽略大小写也是需要考虑的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-11
      • 1970-01-01
      • 2016-03-11
      • 2018-08-16
      • 2012-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多