如何匹配perl正则表达式(regexp)中的重音字符和波浪字符?

如何匹配perl正则表达式(regexp)中的重音字符和波浪字符?,regex,perl,unicode,localization,Regex,Perl,Unicode,Localization,用户输入一组带有重音符号和波浪号的名称: Renato Núñez, David DeJesús, and Edwin Encarnación 我的数据库已经把这些人的名字英文化了 @names = ('Renato Nunez','David DeJesus','Edwin Encarnacion'); 我希望对这些名称进行regexp匹配 $string = "Renato Núñez, David DeJesús, and Edwin Encarnación"; foreach my

用户输入一组带有重音符号和波浪号的名称:

Renato Núñez, David DeJesús, and Edwin Encarnación 
我的数据库已经把这些人的名字英文化了

@names = ('Renato Nunez','David DeJesus','Edwin Encarnacion');
我希望对这些名称进行regexp匹配

$string = "Renato Núñez, David DeJesús, and Edwin Encarnación";
foreach my $name (@names) {
    print "found:$name\n" if ($name =~ /$string/);
}
目前,我没有找到匹配项

我试过了,但没用

$string = "Renato Núñez, David DeJesús, and Edwin Encarnación";
foreach my $name (@names) {
    $name =~ s|a|[áa]|;
    $name =~ s|e|[ée]|;
    $name =~ s|i|[íi]|;
    $name =~ s|o|[óo]|;
    $name =~ s|u|[úu]|;
    $name =~ s|n|[ñn]|;
    # Originally: print "found:$name\n" if ($name =~ /$string/);
    # Corrected to:
    print "found:$name\n" if ($string =~ /$name/);
}
编辑:很抱歉,我在最后一行颠倒了$name和$string


有什么建议吗?

看来您交换了参数。 你打字

试图用“[áa]”替换模式“a” 试一试

交换火柴,它就会起作用

$string = "Renato Núñez, David DeJesús, and Edwin Encarnación";
foreach my $name (@names) {
    print "found:$name\n" if ($string =~ /$name/);
}
  • 从perl 5.6开始,Unicode正则表达式在perl中工作:
  • 您是否检查了源代码编码(拉丁文1或utf8)中的数据库编码

  • 我相信您正在使用字符串“Renato Núñez、David DeJesús和Edwin EncarnacióN”作为regexp

    如果我理解正确的话,你是在试图匹配短语“雷纳托·努涅斯、大卫·德耶斯和埃德温·恩卡纳西翁”中的每一个名字


    如果是这种情况,那么您需要编写:
    $string=~/$name/而不是$name=~/$string/

    这可能更符合您的尝试

    use strict;
    use warnings;
    
    my @AngloNames = ('Renato Nunez','David DeJesus','Edwin Encarnacion');
    my @AngEthRx;
    
    for my $val (@AngloNames) {
       $_ = $val;
       s/a/[áa]/g;
       s/e/[ée]/g;
       s/i/[íi]/g;
       s/o/[óo]/g;
       s/u/[úu]/g;
       s/n/[ñn]/g;
       push @AngEthRx, $_;
    }
    
    # User input query string ...
    my $AngEthQuery = "Renato Núñez, David DeJesús, and Edwin Encarnación";
    
    for my $i (0 .. $#AngEthRx) {
       if ( $AngEthQuery =~ /($AngEthRx[$i])/ ) {
          print "found: $AngloNames[$i] ~ $1\n";
       }
    }
    
    出去

    found:Renato Nunez~Renato Núñez

    found:David DeJesus~David DeJesús


    found:Edwin Encarnacion~Edwin Encarnación

    通过谷歌搜索,我发现问题非常普遍(我使用了查询“perl remove diacritic”)。记住,这不是一门“精确”的科学(去掉发音符号和英语化文本)。这里有一些链接:

    作为建议,对于quick-n-dirty方法:

    • 以规范化形式D规范化字符串(参见此)。例如,这会将“è”更改为“e”+“̀”(组合坟墓,U+0300)
    • 将所有标记(这是一个Unicode类)替换为空字符串。正则表达式基于
      \p{M}
      (它将找到所有标记)
    • 现在,您的字符串没有带变音符号的符号,您可以进行“简单”比较
    • 但请注意,许多“奇怪的字母”幸存了下来:例如,ßØœ。这是一个快速的结束
    我帮不了你更多,因为我已经很多年没有用Perl编程了

    use Unicode::Normalize;
    ($gutted = NFD($string)) =~ s/pM//g;
    
    然而,这几乎总是错误的(est)事情。你打算怎么办

    • var Arnfjörð
    • enanLjubović
    • 亨利八世国王
    • CarlosⅤº,el Emperador
    只要拥抱Unicode。匹配带或不带变音符号的事物的正确方法是实例化强度设置为忽略变音符号的
    Unicode::Collator
    对象。然后只需调用
    cmp
    eq
    方法

    编辑 你应该这样做。证人:

    «La Alberguería de Argañán»    sí tiene /AN/ en  un par de sitios «añ» y «án»
                                   sí tiene /AL/ en     un solo sitio «Al»
    «Bóveda del Río Almar»         sí tiene /AL/ en     un solo sitio «Al»
    «Cabezón de Liébana»           sí tiene /AN/ en     un solo sitio «an»
                                   sí tiene /ON/ en     un solo sitio «ón»
    «Doña Mencía»                  sí tiene /EN/ en     un solo sitio «en»
                                   sí tiene /ON/ en     un solo sitio «oñ»
    «Gallegos de Argañán»          sí tiene /AN/ en  un par de sitios «añ» y «án»
                                   sí tiene /AL/ en     un solo sitio «al»
    «Griñón»                       sí tiene /IN/ en     un solo sitio «iñ»
                                   sí tiene /ON/ en     un solo sitio «ón»
    «Logroño»                      sí tiene /ON/ en     un solo sitio «oñ»
    «Lliçà d’Amunt»                sí tiene /UN/ en     un solo sitio «un»
    «Madroñal»                     sí tiene /ON/ en     un solo sitio «oñ»
                                   sí tiene /AL/ en     un solo sitio «al»
    «Mantilla»                     sí tiene /AN/ en     un solo sitio «an»
    «Mañón»                        sí tiene /AN/ en     un solo sitio «añ»
                                   sí tiene /ON/ en     un solo sitio «ón»
    «Matilla de los Caños del Río» sí tiene /AN/ en     un solo sitio «añ»
    «Montalbán de Córdoba»         sí tiene /AN/ en     un solo sitio «án»
                                   sí tiene /ON/ en     un solo sitio «on»
                                   sí tiene /AL/ en     un solo sitio «al»
    «La Peña»                      sí tiene /EN/ en     un solo sitio «eñ»
    «Piñuécar–Gandullas»           sí tiene /AN/ en     un solo sitio «an»
                                   sí tiene /IN/ en     un solo sitio «iñ»
    «A Pobra do Caramiñal»         sí tiene /IN/ en     un solo sitio «iñ»
                                   sí tiene /AL/ en     un solo sitio «al»
    «Prats de Lluçanès»            sí tiene /AN/ en     un solo sitio «an»
    «Ribamontán al Monte»          sí tiene /AN/ en     un solo sitio «án»
                                   sí tiene /ON/ en  un par de sitios «on» y «on»
                                   sí tiene /AL/ en     un solo sitio «al»
    «La Roca del Vallès»           sí tiene /AL/ en     un solo sitio «al»
    «San Martín del Castañar»      sí tiene /AN/ en  un par de sitios «an» y «añ»
                                   sí tiene /IN/ en     un solo sitio «ín»
    «Santa Eulàlia de Ronçana»     sí tiene /AN/ en  un par de sitios «an» y «an»
                                   sí tiene /ON/ en     un solo sitio «on»
                                   sí tiene /AL/ en     un solo sitio «àl»
    «Santa María de Cayón»         sí tiene /AN/ en     un solo sitio «an»
                                   sí tiene /ON/ en     un solo sitio «ón»
    «Valverde de Alcalá»           sí tiene /AL/ en          3 sitios «al», «Al» y «al»
    «Villar de Argañán»            sí tiene /AN/ en  un par de sitios «añ» y «án»
    
    下面是生成这个的代码

    #!/usr/bin/env perl
    #
    # búsqueda-libre:
    #
    #    Cómo se debiera ordenar y buscar palabras en Unicode
    #    que pueden llevarse marcas diacríticas (o no) sin que
    #    éstas afecten la búsqueda.  También cómo cambiar el
    #    el orden para que no cuente con articulos al principio
    #    del los nombres, como se hace con los títulos de libros &c.
    #
    # Tom Christiansen <tchrist@perl.com>
    # Fri Mar  4 21:06:35 MST 2011
    #
    #############################################
    
    use utf8;
    use 5.10.1;
    use strict;
    use warnings; # FATAL => "all";
    use autodie;
    use charnames qw< :full >;
    
    use List::Util qw< max first >;
    use Unicode::Collate;
    
    my $INCLUÍR_NINGUNOS               = 0;
    my $SI_IMPORTAN_MARCAS_DIACRÍTICAS = 0;
    
    sub sí_ó_no(_) { $_[0] ? "sí" : "no" }
    
    sub encomillar(_) {
        return join $_[0] =>
            "\N{LEFT-POINTING DOUBLE ANGLE QUOTATION MARK}",
            "\N{RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK}",
        ;
    }
    
    binmode(STDOUT, ":utf8");
    # Ésta está demasiada larga para la pantalla. :(
    #
    #    La Ciudad de Nuestra Señora la Reina de Los Ángeles de Porciúncula, California Alta
    #
    
    my @ciudades_españolas = ordenar_a_la_española(<<'LA_ÚLTIMA' =~ /\S.*\S/g);
            Santa Eulàlia de Ronçana
            Mañón
            A Pobra do Caramiñal
            La Alberguería de Argañán
            Logroño
            La Puebla del Río
            Villar de Argañán
            Piñuécar–Gandullas
            Mantilla
            Gallegos de Argañán
            Madroñal
            Griñón
            Lliçà d’Amunt
            Valverde de Alcalá
            Montalbán de Córdoba
            San Martín del Castañar
            La Peña
            Cabezón de Liébana
            Doña Mencía
            Santa María de Cayón
            Bóveda del Río Almar
            La Roca del Vallès
            Matilla de los Caños del Río
            Prats de Lluçanès
            Ribamontán al Monte
    LA_ÚLTIMA
    
    my $cmáx = -(2 + max map { length } @ciudades_españolas);
    
    my @búsquedas = < {A,E,I,O,U}N AL >;
    my $bmáx = -(2 + max map { length } @búsquedas);
    
    my $ordenador = new Unicode::Collate::
                        level           => $SI_IMPORTAN_MARCAS_DIACRÍTICAS ? 2 : 1,
                     ## variable        => "non-ignorable",  # blanked, non-ignorable, shifted, shift-trimmed
                        normalization   => undef,
                    ;
    
    for my $aldea (@ciudades_españolas) {
        my $déjà_imprimée;
        for my $búsqueda (@búsquedas) {
            my @resultados = $ordenador->gmatch($aldea, $búsqueda);
            next unless @resultados || $INCLUÍR_NINGUNOS;
            printf qq(%*s %s tiene %*s en %17s %s\n),
                    $cmáx => !$déjà_imprimée++ && encomillar($aldea),
                    sí_ó_no(@resultados),
                    $bmáx => "/$búsqueda/",
                    cuántos_sitios(@resultados),
                    enfilar(@resultados);
        }
    }
    
    sub cuántos_sitios {
        my @lista = @_;
        my $cantidad = @_;
        given ($cantidad) {
            when (0)  { return    "ningún sitio"    }
            when (1)  { return   "un solo sitio"    }
            when (2)  { return "un par de sitios"   }
            default   { return "$cantidad sitios"   }
        }
    }
    
    sub enfilar {
        my @lista = map { encomillar } @_;
    
        my $separador  = "\N{COMMA}";
           $separador  = "\N{SEMICOLON}"   if first { /$separador/ } @lista;
           $separador .= "\N{SPACE}";
    
        given (scalar @lista) {
            when (0)  { return ""                       }
            when (1)  { return "@lista"                 }
            when (2)  { return join " y " => @lista     }
            default   { return
                join($separador  => @lista[ 0 .. ($#lista-1) ])
                         . " y $lista[$#lista]";
            }
        }
    }
    
    ###################################################
    # Para ordenar los elementos de la lista
    # en el estilo tradicional del castellano.
    #
    # Tenemos en cuenta que sí pueden aparecerse nombres
    # de ciudades que no son nombres sólo castellanos
    # sino tambíen catalanes y gallegos — y tal vez más,
    # como en asturianu or aranés, pero no he pensado
    # mucho es estos.
    ###################################################
    
    sub ordenar_a_la_española {
        my @lista = @_;
    
        state $ordenador_a_la_española = new Unicode::Collate::
    
            # Si se tuviese Unicode::Collate::Locale con "es__traditional",
            # no haría falta este primer lío con su entrada especial,
            # con la excepción de la c-cedilla, la cual aquí se ordena
            # como si fuese catalán, no castellano.
    
            # Vamos a meter las nuevas entradas después de éstas,
            # que son copiadas del DUCET v6.0.0.  Tuve que cambiar unos
            # valores que tenía este código desde otra versión anterior.
            #
            # 0043  ; [.123D.0020.0008.0043] # LATIN CAPITAL LETTER C
            # 00C7  ; [.123D.0020.0008.0043][.0000.0056.0002.0327] # LATIN CAPITAL LETTER C WITH CEDILLA; QQCM
            # 004C  ; [.1330.0020.0008.004C] # LATIN CAPITAL LETTER L
            # 004E  ; [.136D.0020.0008.004E] # LATIN CAPITAL LETTER N
            # 00D1  ; [.136D.0020.0008.004E][.0000.004E.0002.0303] # LATIN CAPITAL LETTER N WITH TILDE; QQCM
    
            entry => <<'SALIDA',   # :)
    
                   00E7      ; [.123E.0020.0002.0327] # c-cedilla
                   0063 0327 ; [.123E.0020.0002.0327] # c-cedilla
                   00C7      ; [.123E.0020.0002.0327] # C-cedilla
                   0043 0327 ; [.123E.0020.0002.0327] # C-cedilla
    
                   0063 0068 ; [.123F.0020.0002.0043] # ch
                   0043 0068 ; [.123F.0020.0007.0043] # Ch
                   0043 0048 ; [.123F.0020.0008.0043] # CH
    
                   006C 006C ; [.1331.0020.0002.004C] # ll
                   004C 006C ; [.1331.0020.0007.004C] # Ll
                   004C 004C ; [.1331.0020.0008.004C] # LL
    
                   00F1      ; [.136E.0020.0002.0303] # n-tilde
                   006E 0303 ; [.136E.0020.0002.0303] # n-tilde
                   00D1      ; [.136E.0020.0008.0303] # N-tilde
                   004E 0303 ; [.136E.0020.0008.0303] # N-tilde
    
    SALIDA
    
           upper_before_lower => 1,
    
           normalization => "NFKD",  # ¿Y porqué no?
    
           preprocess => sub {
               my $_ = shift;
    
           ###
           # no incluye los artículos definitivos ni indefinitivos
           ###
    
               s/^L\p{QMARK}//;    # puede encontrarse en el catalán
    
               s{ ^
    
                 (?:         # del castellano
                     El
                   | Los
                   | La
                   | Las
                             # del catalán
                   | Els
                   | Les
                   | Sa
                   | Es
                             # del gallego
                   | O
                   | Os
                   | A
                   | As
                 )
    
                 \h +
    
              }{}x;
    
            # Luego quita las palabras no-importantes interiores.
    
               s/\b[dl]\p{QMARK}//g;   # del catalán
    
               s{
                   \b
                   (?:
                       el  | los | la | las | de  | del | y          # ES
                     | els | les | i  | sa  | es  | dels             # CA
                     | o   | os  | a  | as  | do  | da | dos | das   # GAL
                   )
                   \b
               }{}gx;
    
              return $_;
    
           },   # fin de rutina preprocesadora
    
      ## ¡Fijaos que no borréis esta marca!
      ##     Este punto y coma marca el fin
      ##     de los argumentos del constructor
      ##     empezado ya muchas lineas arriba.
      ##   ˅
           ;  # ←←← Sí, ése — dejadlo en paz o muy tristes os quedaréis.
      ##   ˄
    
        return $ordenador_a_la_española->sort(@lista);
    }
    
    #/usr/bin/env perl
    #
    #búsqueda libre:
    #
    #Cómo se debiera ordenar y buscar palabras en Unicode
    #你知道吗?你知道吗
    #这是一个很好的例子。塔姆比恩·科莫·坎比亚尔酒店
    #这是一个原则性的协议
    #科摩罗的nombres街上有一家图书馆。
    #
    #汤姆克里斯汀森
    #2011年3月4日星期五21:06:35 MST
    #
    #############################################
    使用utf8;
    使用5.10.1;
    严格使用;
    使用警告;#致命=>“全部”;
    使用自动模具;
    使用字符名qw<:full>;
    使用列表::Util qw;
    使用Unicode::Collate;
    我的$INCLUÍR_NINGUNOS=0;
    我的$SI_IMPORTAN_MARCAS_diacarÍTICAS=0;
    sub-síuoóu no({${[0]?“sí”:“no”}
    副磨机{
    return join$\u0]=>
    “\N{左指双角度引号}”,
    “\N{右指双角度引号}”,
    ;
    }
    binmode(标准输出,“:utf8”);
    #埃斯塔·埃斯塔·德马西亚达·拉加·帕塔拉:(
    #
    #加利福尼亚州阿尔塔波奇库拉大教堂(La Ciudad de Nuestra Señora La Reina de LosÁngeles de Porciúncula)
    #
    我的@ciudades_españolas=ordenar_a_la_española($SI_IMPORTAN_MARCASÍdiacarÍTICAS?2:1,
    ##变量=>“不可忽略”、#消隐、不可忽略、移位、移位修剪
    标准化=>未定义,
    ;
    我的$aldea(@ciudades_españolas){
    我的$déjéu即兴演出;
    为了我的$búsqueda(@búsquedas){
    my@resultados=$ordenador->gmatch($aldea,$búsqueda);
    下一步除非@resultados | |$INCLUÍR|NINGUNOS;
    printf qq(%*s%s tiene%*s en%17s%s\n),
    $cmáx=>!$déjáu imprime++&&encomillar($aldea),
    síuoóu no(@resultados),
    $bmáx=>“/$búsqueda/”,
    cuántos_sitios(@resultados),
    enfilar(@resultados);
    }
    }
    sub cuántos_sitios{
    我的@lista=@;
    我的$cantidad=@;
    给定($cantidad){
    当(0){返回“ningún sitio”}
    当(1){返回“un solo sitio”}
    当(2){返回“unsi-sisithOS”}时
    默认值{返回“$cantidad sitios”}
    }
    }
    亚微丝{
    my@lista=map{encomillar}@;
    my$separador=“\N{COMMA}”;
    $separador=“\N{分号}”如果第一个{/$separador/}@lista;
    $separador.=“\N{SPACE}”;
    给定(标量@lista){
    当(0){return”“}
    当(1){return“@lista”}
    当(2){return join“y”=>@lista}
    默认{返回
    加入($separador=>@lista[0..($#lista-1)])
    “y$lista[$#lista]”;
    }
    }
    }
    ###################################################
    #利斯塔元素酒店
    #卡斯特拉诺传统酒店。
    #
    #Tenemos en cuenta que sípueden Apareserve nombres
    #没有一个儿子是卡斯特拉诺斯
    #中泰两国加泰罗尼亚人和加列戈斯-塔尔维兹·马斯,
    #在阿斯图里亚努或阿兰内斯,我不知道该怎么做
    #许多
    
    «La Alberguería de Argañán»    sí tiene /AN/ en  un par de sitios «añ» y «án»
                                   sí tiene /AL/ en     un solo sitio «Al»
    «Bóveda del Río Almar»         sí tiene /AL/ en     un solo sitio «Al»
    «Cabezón de Liébana»           sí tiene /AN/ en     un solo sitio «an»
                                   sí tiene /ON/ en     un solo sitio «ón»
    «Doña Mencía»                  sí tiene /EN/ en     un solo sitio «en»
                                   sí tiene /ON/ en     un solo sitio «oñ»
    «Gallegos de Argañán»          sí tiene /AN/ en  un par de sitios «añ» y «án»
                                   sí tiene /AL/ en     un solo sitio «al»
    «Griñón»                       sí tiene /IN/ en     un solo sitio «iñ»
                                   sí tiene /ON/ en     un solo sitio «ón»
    «Logroño»                      sí tiene /ON/ en     un solo sitio «oñ»
    «Lliçà d’Amunt»                sí tiene /UN/ en     un solo sitio «un»
    «Madroñal»                     sí tiene /ON/ en     un solo sitio «oñ»
                                   sí tiene /AL/ en     un solo sitio «al»
    «Mantilla»                     sí tiene /AN/ en     un solo sitio «an»
    «Mañón»                        sí tiene /AN/ en     un solo sitio «añ»
                                   sí tiene /ON/ en     un solo sitio «ón»
    «Matilla de los Caños del Río» sí tiene /AN/ en     un solo sitio «añ»
    «Montalbán de Córdoba»         sí tiene /AN/ en     un solo sitio «án»
                                   sí tiene /ON/ en     un solo sitio «on»
                                   sí tiene /AL/ en     un solo sitio «al»
    «La Peña»                      sí tiene /EN/ en     un solo sitio «eñ»
    «Piñuécar–Gandullas»           sí tiene /AN/ en     un solo sitio «an»
                                   sí tiene /IN/ en     un solo sitio «iñ»
    «A Pobra do Caramiñal»         sí tiene /IN/ en     un solo sitio «iñ»
                                   sí tiene /AL/ en     un solo sitio «al»
    «Prats de Lluçanès»            sí tiene /AN/ en     un solo sitio «an»
    «Ribamontán al Monte»          sí tiene /AN/ en     un solo sitio «án»
                                   sí tiene /ON/ en  un par de sitios «on» y «on»
                                   sí tiene /AL/ en     un solo sitio «al»
    «La Roca del Vallès»           sí tiene /AL/ en     un solo sitio «al»
    «San Martín del Castañar»      sí tiene /AN/ en  un par de sitios «an» y «añ»
                                   sí tiene /IN/ en     un solo sitio «ín»
    «Santa Eulàlia de Ronçana»     sí tiene /AN/ en  un par de sitios «an» y «an»
                                   sí tiene /ON/ en     un solo sitio «on»
                                   sí tiene /AL/ en     un solo sitio «àl»
    «Santa María de Cayón»         sí tiene /AN/ en     un solo sitio «an»
                                   sí tiene /ON/ en     un solo sitio «ón»
    «Valverde de Alcalá»           sí tiene /AL/ en          3 sitios «al», «Al» y «al»
    «Villar de Argañán»            sí tiene /AN/ en  un par de sitios «añ» y «án»
    
    #!/usr/bin/env perl
    #
    # búsqueda-libre:
    #
    #    Cómo se debiera ordenar y buscar palabras en Unicode
    #    que pueden llevarse marcas diacríticas (o no) sin que
    #    éstas afecten la búsqueda.  También cómo cambiar el
    #    el orden para que no cuente con articulos al principio
    #    del los nombres, como se hace con los títulos de libros &c.
    #
    # Tom Christiansen <tchrist@perl.com>
    # Fri Mar  4 21:06:35 MST 2011
    #
    #############################################
    
    use utf8;
    use 5.10.1;
    use strict;
    use warnings; # FATAL => "all";
    use autodie;
    use charnames qw< :full >;
    
    use List::Util qw< max first >;
    use Unicode::Collate;
    
    my $INCLUÍR_NINGUNOS               = 0;
    my $SI_IMPORTAN_MARCAS_DIACRÍTICAS = 0;
    
    sub sí_ó_no(_) { $_[0] ? "sí" : "no" }
    
    sub encomillar(_) {
        return join $_[0] =>
            "\N{LEFT-POINTING DOUBLE ANGLE QUOTATION MARK}",
            "\N{RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK}",
        ;
    }
    
    binmode(STDOUT, ":utf8");
    # Ésta está demasiada larga para la pantalla. :(
    #
    #    La Ciudad de Nuestra Señora la Reina de Los Ángeles de Porciúncula, California Alta
    #
    
    my @ciudades_españolas = ordenar_a_la_española(<<'LA_ÚLTIMA' =~ /\S.*\S/g);
            Santa Eulàlia de Ronçana
            Mañón
            A Pobra do Caramiñal
            La Alberguería de Argañán
            Logroño
            La Puebla del Río
            Villar de Argañán
            Piñuécar–Gandullas
            Mantilla
            Gallegos de Argañán
            Madroñal
            Griñón
            Lliçà d’Amunt
            Valverde de Alcalá
            Montalbán de Córdoba
            San Martín del Castañar
            La Peña
            Cabezón de Liébana
            Doña Mencía
            Santa María de Cayón
            Bóveda del Río Almar
            La Roca del Vallès
            Matilla de los Caños del Río
            Prats de Lluçanès
            Ribamontán al Monte
    LA_ÚLTIMA
    
    my $cmáx = -(2 + max map { length } @ciudades_españolas);
    
    my @búsquedas = < {A,E,I,O,U}N AL >;
    my $bmáx = -(2 + max map { length } @búsquedas);
    
    my $ordenador = new Unicode::Collate::
                        level           => $SI_IMPORTAN_MARCAS_DIACRÍTICAS ? 2 : 1,
                     ## variable        => "non-ignorable",  # blanked, non-ignorable, shifted, shift-trimmed
                        normalization   => undef,
                    ;
    
    for my $aldea (@ciudades_españolas) {
        my $déjà_imprimée;
        for my $búsqueda (@búsquedas) {
            my @resultados = $ordenador->gmatch($aldea, $búsqueda);
            next unless @resultados || $INCLUÍR_NINGUNOS;
            printf qq(%*s %s tiene %*s en %17s %s\n),
                    $cmáx => !$déjà_imprimée++ && encomillar($aldea),
                    sí_ó_no(@resultados),
                    $bmáx => "/$búsqueda/",
                    cuántos_sitios(@resultados),
                    enfilar(@resultados);
        }
    }
    
    sub cuántos_sitios {
        my @lista = @_;
        my $cantidad = @_;
        given ($cantidad) {
            when (0)  { return    "ningún sitio"    }
            when (1)  { return   "un solo sitio"    }
            when (2)  { return "un par de sitios"   }
            default   { return "$cantidad sitios"   }
        }
    }
    
    sub enfilar {
        my @lista = map { encomillar } @_;
    
        my $separador  = "\N{COMMA}";
           $separador  = "\N{SEMICOLON}"   if first { /$separador/ } @lista;
           $separador .= "\N{SPACE}";
    
        given (scalar @lista) {
            when (0)  { return ""                       }
            when (1)  { return "@lista"                 }
            when (2)  { return join " y " => @lista     }
            default   { return
                join($separador  => @lista[ 0 .. ($#lista-1) ])
                         . " y $lista[$#lista]";
            }
        }
    }
    
    ###################################################
    # Para ordenar los elementos de la lista
    # en el estilo tradicional del castellano.
    #
    # Tenemos en cuenta que sí pueden aparecerse nombres
    # de ciudades que no son nombres sólo castellanos
    # sino tambíen catalanes y gallegos — y tal vez más,
    # como en asturianu or aranés, pero no he pensado
    # mucho es estos.
    ###################################################
    
    sub ordenar_a_la_española {
        my @lista = @_;
    
        state $ordenador_a_la_española = new Unicode::Collate::
    
            # Si se tuviese Unicode::Collate::Locale con "es__traditional",
            # no haría falta este primer lío con su entrada especial,
            # con la excepción de la c-cedilla, la cual aquí se ordena
            # como si fuese catalán, no castellano.
    
            # Vamos a meter las nuevas entradas después de éstas,
            # que son copiadas del DUCET v6.0.0.  Tuve que cambiar unos
            # valores que tenía este código desde otra versión anterior.
            #
            # 0043  ; [.123D.0020.0008.0043] # LATIN CAPITAL LETTER C
            # 00C7  ; [.123D.0020.0008.0043][.0000.0056.0002.0327] # LATIN CAPITAL LETTER C WITH CEDILLA; QQCM
            # 004C  ; [.1330.0020.0008.004C] # LATIN CAPITAL LETTER L
            # 004E  ; [.136D.0020.0008.004E] # LATIN CAPITAL LETTER N
            # 00D1  ; [.136D.0020.0008.004E][.0000.004E.0002.0303] # LATIN CAPITAL LETTER N WITH TILDE; QQCM
    
            entry => <<'SALIDA',   # :)
    
                   00E7      ; [.123E.0020.0002.0327] # c-cedilla
                   0063 0327 ; [.123E.0020.0002.0327] # c-cedilla
                   00C7      ; [.123E.0020.0002.0327] # C-cedilla
                   0043 0327 ; [.123E.0020.0002.0327] # C-cedilla
    
                   0063 0068 ; [.123F.0020.0002.0043] # ch
                   0043 0068 ; [.123F.0020.0007.0043] # Ch
                   0043 0048 ; [.123F.0020.0008.0043] # CH
    
                   006C 006C ; [.1331.0020.0002.004C] # ll
                   004C 006C ; [.1331.0020.0007.004C] # Ll
                   004C 004C ; [.1331.0020.0008.004C] # LL
    
                   00F1      ; [.136E.0020.0002.0303] # n-tilde
                   006E 0303 ; [.136E.0020.0002.0303] # n-tilde
                   00D1      ; [.136E.0020.0008.0303] # N-tilde
                   004E 0303 ; [.136E.0020.0008.0303] # N-tilde
    
    SALIDA
    
           upper_before_lower => 1,
    
           normalization => "NFKD",  # ¿Y porqué no?
    
           preprocess => sub {
               my $_ = shift;
    
           ###
           # no incluye los artículos definitivos ni indefinitivos
           ###
    
               s/^L\p{QMARK}//;    # puede encontrarse en el catalán
    
               s{ ^
    
                 (?:         # del castellano
                     El
                   | Los
                   | La
                   | Las
                             # del catalán
                   | Els
                   | Les
                   | Sa
                   | Es
                             # del gallego
                   | O
                   | Os
                   | A
                   | As
                 )
    
                 \h +
    
              }{}x;
    
            # Luego quita las palabras no-importantes interiores.
    
               s/\b[dl]\p{QMARK}//g;   # del catalán
    
               s{
                   \b
                   (?:
                       el  | los | la | las | de  | del | y          # ES
                     | els | les | i  | sa  | es  | dels             # CA
                     | o   | os  | a  | as  | do  | da | dos | das   # GAL
                   )
                   \b
               }{}gx;
    
              return $_;
    
           },   # fin de rutina preprocesadora
    
      ## ¡Fijaos que no borréis esta marca!
      ##     Este punto y coma marca el fin
      ##     de los argumentos del constructor
      ##     empezado ya muchas lineas arriba.
      ##   ˅
           ;  # ←←← Sí, ése — dejadlo en paz o muy tristes os quedaréis.
      ##   ˄
    
        return $ordenador_a_la_española->sort(@lista);
    }