Rails和Django等Web框架内置了对“slugs”的支持,用于生成可读和SEO友好的URL:
slug字符串通常只包含字符a-z
,0-9
和-
,因此可以在没有URL转义的情况下编写(想想“foo%20bar”)。
我正在寻找一个Perl slug函数,给定任何有效的Unicode字符串将返回一个slug表示(a-z
,0-9
和-
)。
一个超级微不足道的slug功能将是:
$input = lc($input),
$input =~ s/[^a-z0-9-]//g;
但是,此实现不会处理国际化和重音(我希望ë
成为e
)。解决这个问题的一种方法是列举所有特殊情况,但这不是很优雅。我正在寻找更好的思考和一般性的东西。
我的问题:
答案 0 :(得分:12)
Django中当前使用的slugify
filter(大致)转换为以下Perl代码:
use Unicode::Normalize;
sub slugify($) {
my ($input) = @_;
$input = NFKD($input); # Normalize (decompose) the Unicode string
$input =~ tr/\000-\177//cd; # Strip non-ASCII characters (>127)
$input =~ s/[^\w\s-]//g; # Remove all characters that are not word characters (includes _), spaces, or hyphens
$input =~ s/^\s+|\s+$//g; # Trim whitespace from both ends
$input = lc($input);
$input =~ s/[-\s]+/-/g; # Replace all occurrences of spaces and hyphens with a single hyphen
return $input;
}
由于您还想将重音字符更改为非重音字符,因此在剥离非ASCII字符之前抛出对unidecode
(在Text::Unidecode
中定义)的调用似乎是您最好的选择({{ 3}})。
在这种情况下,该功能可能如下所示:
use Unicode::Normalize;
use Text::Unidecode;
sub slugify_unidecode($) {
my ($input) = @_;
$input = NFC($input); # Normalize (recompose) the Unicode string
$input = unidecode($input); # Convert non-ASCII characters to closest equivalents
$input =~ s/[^\w\s-]//g; # Remove all characters that are not word characters (includes _), spaces, or hyphens
$input =~ s/^\s+|\s+$//g; # Trim whitespace from both ends
$input = lc($input);
$input =~ s/[-\s]+/-/g; # Replace all occurrences of spaces and hyphens with a single hyphen
return $input;
}
前者适用于主要是ASCII的字符串,但是当整个字符串由非ASCII字符组成时,它们会很短,因为它们都被剥离,留下一个空字符串。
示例输出:
string | slugify | slugify_unidecode
-------------------------------------------------
hello world hello world hello world
北亰 bei-jing
liberté liberta liberte
请注意,使用Django启发的实现,北how如何变得毫无结果。还要注意NFC标准化所带来的差异 - 在剥离分解字符的第二部分后,liberté变成了NFKD的“自由”,但在用NFC去掉重新组装的“é”之后会变得“自由”。
答案 1 :(得分:3)
您是否在寻找Text::Unidecode之类的内容?
答案 2 :(得分:3)
String::Dirify
用于在博客软件Movable Type / Melody中制作slu ..
答案 3 :(得分:1)
将Text::Unaccent添加到链的开头看起来就像它会做你想要的。
答案 4 :(得分:0)
最直接的解决方案是使用Text::Slugify来完成您的需要。这是一个微不足道的代码,可以很好地为您提供slugify
函数。
它依赖于Text::Unaccent::PurePerl来删除字符的重音。