2017-05-03 71 views
2
#!/usr/bin/perl -T 
use strict; 
use warnings; 
use utf8; 
my $s = shift || die; 
$s =~ s/[^A-Za-z ]//g; 
print "$s\n"; 
exit; 

> ./poc.pl "El Guapö" 
El Guap 

有没有办法修改此Perl代码,以便各种元音变音和字符口音不会被剥离?谢谢!带字符串,但允许变音符号

+2

当然,将它们添加到角色类? – sln

+0

是否要保留例如中国文字? – melpomene

+1

你在意口音的组合吗?例如。如果你有拉丁小写字母O,然后是合并DIAERESIS,你想保留它们两个吗? – melpomene

回答

7

对于直接的问题,你可能只需要\p{L}(信纸)Unicode Character Property

然而,更重要的是,解码所有的输入和输出编码

use warnings; 
use strict; 
use feature 'say'; 

use utf8; # allow non-ascii (UTF-8) characters in the source 

use open ':std', ':encoding(UTF-8)'; # for standard streams 

use Encode qw(decode_utf8);   # @ARGV escapes the above 

my $string = 'El Guapö'; 
if (@ARGV) { 
    $string = join ' ', map { decode_utf8($_) } @ARGV; 
} 
say "Input:  $string"; 

$string =~ s/[^\p{L} ]//g; 

say "Processed: $string"; 

当作为  script.pl 123 El Guapö=_

 
Input:  123 El Guapö=_ 
Processed: El Guapö 

我用 “一刀切” \p{L}财产(),具体描述是缺乏运行;根据需要调整。 Unicode属性提供了很多,请参阅上面的链接以及perluniprops的完整列表。

123 El之间的空间依然存在,可能会剥离最后的空间(和尾部)。

请注意,还有\P{L},其中首都P表示否定。


以上笨笨\pL不会Combining Diacritical Marks工作,作为标记也将被删除。感谢jm666指出了这一点。

当使用单独字符作为其基本字符和非间距标记(合并口音)来重写“逻辑”字符(显示为单个字符)时,会发生这种情况。它的代码点通常只有一个字符(extended grapheme cluster)也存在。例如: ñU+OOF1但它也可以写为"n\x{303}"

为了保持这样的写法添加\p{Mn}\p{NonspacingMark})口音的字符类

my $string = "El Guapö=_ ni\N{U+00F1}o.* nin\x{303}o+^"; 
say $string; 

(my $nodiac = $string) =~ s/[^\pL ]//g;  #/ naive, accent chars get removed 
say $nodiac; 

(my $full = $string) =~ s/[^\pL\p{Mn} ]//g; # add non-spacing mark 
say $full; 

输出

 
El Guapö=_ niño.* niño+^ 
El Guapö niño nino 
El Guapö niño niño 

所以你为了保持组合口音想s/[^\p{L}\p{Mn} ]//g

+1

@ jm666感谢您的评论。我并不十分关心确切的正则表达式,因为OP没有多说 - 我认为其余更重要。你是对的,需要把'\ pM'放入字符类中......将会添加一个例子。 – zdim

+0

我有点理解。我的最终目的是解开CGI输入,存储在MySQL中,然后在HTML中进行检索和使用。我的困惑在于解码/编码。在数据库中存储解码值并在使用前进行编码是否正确?我需要正确处理客户输入的古怪东西,我现在将其退出。谢谢! –

+0

@TimothyB。你已经倒过来了。在将其存储在数据库中之前,您需要* en *代码,并在再次将其拉出时使用* de *代码。如果您使用的是DBI,并且您的数据库和数据库句柄设置正确,则可以为您完成。 –

相关问题