用于生成slugs的Java代码/库(用于漂亮的URL)

kno*_*orv 37 java regex seo url-rewriting slug

诸如Rails和Django之类的Web框架内置了对"slugs"的支持,后者用于生成可读和SEO友好的URL:

团状串典型地只包含的字符a-z,0-9-且可因此在不URL转义写入(认为"富%20巴").

我正在寻找一个Java slug函数,给出任何有效的Unicode字符串将返回一个slug表示(a-z,0-9-).

一个微不足道的slug函数将是这样的:

return input.toLowerCase().replaceAll("[^a-z0-9-]", "");
Run Code Online (Sandbox Code Playgroud)

但是,此实现不会处理国际化和重音(ë> e).解决这个问题的一种方法是列举所有特殊情况,但这不是很优雅.我正在寻找更好的思考和一般的东西.

我的问题:

  • 在Java中生成Django/Rails类型slugs的最通用/最实用的方法是什么?

McD*_*ell 39

使用规范分解规范化字符串:

  private static final Pattern NONLATIN = Pattern.compile("[^\\w-]");
  private static final Pattern WHITESPACE = Pattern.compile("[\\s]");

  public static String toSlug(String input) {
    String nowhitespace = WHITESPACE.matcher(input).replaceAll("-");
    String normalized = Normalizer.normalize(nowhitespace, Form.NFD);
    String slug = NONLATIN.matcher(normalized).replaceAll("");
    return slug.toLowerCase(Locale.ENGLISH);
  }
Run Code Online (Sandbox Code Playgroud)

不过,这仍然是一个相当天真的过程.它不会对s-sharp(ß - 德语中使用)或任何非拉丁语字母表(希腊语,西里尔语,CJK等)做任何事情.

更改字符串的大小写时要小心.大写和小写形式取决于字母表.在土耳其语中,U + 0069(i)的大写字母是U + 0130(İ),而不是U + 0049(I),因此如果您String.toLowerCase()在土耳其语语言环境下使用,则可能会冒险将非latin1字符引入字符串.

  • 奇怪 - 当我通过方法输入字符串 `"f\u00F3\u00F2b\u00e2r"` 时,我得到了 `"foobar"`。您可能在源文件或数据文件中出现编码错误;见 http://illegalargumentexception.blogspot.com/2009/05/java-rough-guide-to-character-encoding.html (2认同)

dtr*_*unk 13

http://search.maven.org/#search|ga|1|slugify

这里是GitHub存储库,用于查看代码及其用法:

https://github.com/slugify/slugify


Mik*_*din 5

我已经扩展了@McDowell 的答案,以将标点符号转义为连字符并删除重复的和前导/尾随连字符。

  private static final Pattern NONLATIN = Pattern.compile("[^\\w_-]");  
  private static final Pattern SEPARATORS = Pattern.compile("[\\s\\p{Punct}&&[^-]]");  

  public static String makeSlug(String input) {  
    String noseparators = SEPARATORS.matcher(input).replaceAll("-");
    String normalized = Normalizer.normalize(noseparators, Form.NFD);
    String slug = NONLATIN.matcher(normalized).replaceAll("");
    return slug.toLowerCase(Locale.ENGLISH).replaceAll("-{2,}","-").replaceAll("^-|-$","");
  }
Run Code Online (Sandbox Code Playgroud)


Mar*_*uiz 5

McDowel的命题几乎可行,但是在这种情况下,Hello World !!它返回hello-world--(请注意--字符串末尾的)而不是hello-world

固定版本可以是:

private static final Pattern NONLATIN = Pattern.compile("[^\\w-]");
private static final Pattern WHITESPACE = Pattern.compile("[\\s]");
private static final Pattern EDGESDHASHES = Pattern.compile("(^-|-$)");

public static String toSlug(String input) {
    String nowhitespace = WHITESPACE.matcher(input).replaceAll("-");
    String normalized = Normalizer.normalize(nowhitespace, Normalizer.Form.NFD);
    String slug = NONLATIN.matcher(normalized).replaceAll("");
    slug = EDGESDHASHES.matcher(slug).replaceAll("");
    return slug.toLowerCase(Locale.ENGLISH);
}
Run Code Online (Sandbox Code Playgroud)