搜索与特殊字符相似的字符

Search for Characters Similar to Special Characters

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

例如,单词 "Náufragos" 输入为 "Naufragos"。

现在,当在上述数据文件中搜索 "Náufragos" 时,我使用 grep 查找 "Náufragos" 并且搜索结果为空(应该是这样),但我确实需要上述搜索才能找到并输出 "Naufragos".

我梳理了 grep 文档并在 Google 上进行了大量搜索,但一无所获。

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

是否有 grep 或 perl 选项可以执行此操作?也许是这样的:

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

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

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

匹配名称的任一拼写,如果这很麻烦,使用Text::Unidecode as discussed in 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;

但是,更好的脚本会匹配两个 old/new 名称,因为很容易忽略已转换的文件。是否忽略大小写也是需要考虑的问题。

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

#!/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

好多了。