【问题标题】:Strip string but allow umlauts剥离字符串但允许变音
【发布时间】:2017-10-01 23:21:54
【问题描述】:
#!/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 代码,以便不去除各种变音符号和字符重音符号?谢谢!

【问题讨论】:

  • 好的,将它们添加到字符类中?
  • 你想保留例如汉字?
  • 您是否关心组合口音?例如。如果你有拉丁小写字母 O 后跟 COMBINING DIAERESIS,你想保留它们吗?

标签: regex perl diacritics


【解决方案1】:

对于直接问题,您可能只需要\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ö=_ 运行时

输入:123 El Guapö=_ 加工:El Guapö

我使用了“毯子”\p{L} 属性(字母),因为缺少具体描述;如果/根据需要进行调整。 Unicode 属性提供了很多,请参阅上面的链接和perluniprops 的完整列表。

123 El 之间的空格仍然存在,最后可能会去掉前导(和尾随)空格。

注意还有\P{L},其中大写P表示否定。


上述简单的\pL 不适用于Combining Diacritical Marks,因为标记也会被删除。感谢jm666 指出这一点。

当重音“逻辑”字符(显示为单个字符)使用单独的字符作为其基字符和非空格标记(组合重音)时,就会发生这种情况。通常它的单个字符 (extended grapheme cluster) 及其代码点也存在。

例如:niño 中的ñ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 以保持组合重音。

【讨论】:

  • @jm666 感谢您的评论。我不太关心确切的正则表达式,因为 OP 并没有说太多——我认为其余的真的更重要。你是对的,需要将\pM 放入字符类中......将添加一个示例。
  • 我有点明白。我的最终目的是清除 CGI 输入,存储在 MySQL 中,然后在 HTML 中检索和使用。我的困惑在于解码/编码。将解码值存储在数据库中并在使用前进行编码是否合适?我需要正确处理客户输入的我目前删除的古怪内容。谢谢!
  • @TimothyB。你把它弄反了。您需要在将其存储到数据库之前en编码,并在再次将其拉回时de编码。如果您使用的是 DBI,并且您的数据库和数据库句柄设置正确,那么您就可以完成。
  • 谢谢!这就是我最终的结果。 DBI 连接使用 mysql_enable_utf8。解码未污染的 param() 输入。写入数据库。从数据库中读取。编码并在 HTML 中正确显示。奖励:我可以在 MySQL 中搜索“nino”(纯文本)并且它匹配。我已经启动并运行了。我在这里提到它,以防我仍然做错了什么。
  • @TimothyB。正如马特所说,由于它是数据库,我们为我们做了很多事情,但请睁大眼睛。在您的程序中,您希望对进来的所有内容进行解码以进行处理,然后对其进行编码以进行输出。确保您的 HTML 也指定了编码。你说的很好。
猜你喜欢
  • 1970-01-01
  • 2010-09-19
  • 2012-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-20
相关资源
最近更新 更多