2017-05-03 68 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,並且您的數據庫和數據庫句柄設置正確,則可以爲您完成。 –

相關問題