【问题标题】:Convert string into slug with single-hyphen delimiters only仅使用单连字符分隔符将字符串转换为 slug
【发布时间】:2011-03-02 14:52:31
【问题描述】:

我想将一个字符串清理到一个 URL 中,所以这就是我基本上需要的:

  1. 必须删除除字母数字字符和空格以及虚线之外的所有内容。
  2. 空格应转换为破折号。

例如。

This, is the URL!

必须返回

this-is-the-url

【问题讨论】:

  • 嗨 jens,我对代码一无所知,这就是我需要帮助的地方。我唯一知道的是它应该使用 preg_replace() 但我不知道正则表达式应该是什么。谢谢

标签: php regex preg-replace slug sanitization


【解决方案1】:
function slug($z){
    $z = strtolower($z);
    $z = preg_replace('/[^a-z0-9 -]+/', '', $z);
    $z = str_replace(' ', '-', $z);
    return trim($z, '-');
}

【讨论】:

  • 非常感谢.. 只需一次编辑.. 我想在返回 $z 之前从开头和结尾删除破折号,以防万一它们存在。
  • -1:在字里行间阅读 SilentGhost 意图,而不是他/她编写的代码。这似乎是 url 安全的,但以丢失信息为代价。为 URL 编码数据的正确方法是使用 urlencode()。
  • (我看到它做了示例中所示的翻译 - 但不是 atif089 要求的)
  • @symcbean urlcode 不是我需要的,因为我想消除符号而不是转换它们。所以这正是我想要的。
  • @mario: 1. 它不做同样的处理; 2. 这是维护的噩梦。
【解决方案2】:

首先去除不需要的字符

$new_string = preg_replace("/[^a-zA-Z0-9\s]/", "", $string);

然后将空格换成 unsercores

$url = preg_replace('/\s/', '-', $new_string);

最后编码准备好使用

$new_url = urlencode($url);

【讨论】:

  • 下划线是一个不同的字符:_ 是一个下划线,- 是一个连字符。在这样的字符串上使用urlencode 也不会改变任何东西。您还忘记了第一个正则表达式中的 hypen 并且 \s 不等于空格字符。
【解决方案3】:

这将在 Unix shell 中完成(我刚刚在我的 MacOS 上尝试过):

$ tr -cs A-Za-z '-' < infile.txt > outfile.txt

我从 More Shell, Less Egg 上的一篇博文中得到了这个想法

【讨论】:

    【解决方案4】:

    试试这个

     function clean($string) {
           $string = str_replace(' ', '-', $string); // Replaces all spaces with hyphens.
           $string = preg_replace('/[^A-Za-z0-9\-]/', '', $string); // Removes special chars.
    
           return preg_replace('/-+/', '-', $string); // Replaces multiple hyphens with single one.
        }
    

    用法:

    echo clean('a|"bc!@£de^&$f g');
    

    将输出:abcdef-g

    来源:https://stackoverflow.com/a/14114419/2439715

    【讨论】:

      【解决方案5】:

      所有以前的 asnwers 都处理 url,但如果有人需要清理字符串以进行登录(例如)并将其保留为文本,那么你可以这样做:

      function sanitizeText($str) {
          $withSpecCharacters = htmlspecialchars($str);
          $splitted_str = str_split($str);
          $result = '';
          foreach ($splitted_str as $letter){
              if (strpos($withSpecCharacters, $letter) !== false) {
                  $result .= $letter;
              }
          }
          return $result;
      }
      
      echo sanitizeText('ОРРииыфвсси ajvnsakjvnHB "&nvsp;\n" <script>alert()</script>');
      //ОРРииыфвсси ajvnsakjvnHB &nvsp;\n scriptalert()/script
      //No injections possible, all info at max keeped
      

      【讨论】:

        【解决方案6】:

        以下内容将用破折号替换空格。

        $str = str_replace(' ', '-', $str);
        

        然后以下语句将删除除字母数字字符和虚线之外的所有内容。 (没有空格,因为在上一步中我们已将它们替换为破折号。

        // Char representation     0 -  9   A-   Z   a-   z  -    
        $str = preg_replace('/[^\x30-\x39\x41-\x5A\x61-\x7A\x2D]/', '', $str);
        

        相当于

        $str = preg_replace('/[^0-9A-Za-z-]+/', '', $str);
        

        仅供参考:要从字符串中删除所有特殊字符,请使用

        $str = preg_replace('/[^\x20-\x7E]/', '', $str); 
        

        \x20 是 Acsii 字符开头的空间的十六进制,\x7E 是波浪号。根据维基百科https://en.wikipedia.org/wiki/ASCII#Printable_characters

        仅供参考:查看 20-7E 区间的十六进制列

        可打印字符 代码 20hex 到 7Ehex 被称为可打印字符,代表字母、数字、标点符号和一些杂项符号。总共有 95 个可打印字符。

        【讨论】:

        【解决方案7】:

        你应该使用 slugify 包而不是重新发明轮子;)

        https://github.com/cocur/slugify

        【讨论】:

        • 仅链接的答案是没有用的,尤其是当它会被破坏时。你能详细说明一下吗?
        • 最好将包推荐为问题下的评论。
        【解决方案8】:
            function isolate($data) {
                
                $data = trim($data);
                $data = stripslashes($data);
                $data = htmlspecialchars($data);
                
                return $data;
            }
        

        【讨论】:

        • 请在您的代码中添加更多信息,可能是如何使用或如何获得此答案。谢谢。
        【解决方案9】:

        OP 没有明确描述 slug 的所有属性,但这是我从意图中收集到的。

        我对完美、有效、浓缩的 slug 的解释与这篇文章一致:https://wordpress.stackexchange.com/questions/149191/slug-formatting-acceptable-characters#:~:text=However%2C%20we%20can%20summarise%20the,or%20end%20with%20a%20hyphen

        我发现之前发布的答案中没有一个能够始终如一地实现这一目标(而且我什至没有将问题的范围扩大到包括多字节字符)。

        1. 将所有字符转换为小写
        2. 将一个或多个非字母数字字符的所有序列替换为单个连字符。
        3. 从字符串中删除前导和尾随连字符。

        我推荐以下不打扰声明一次性变量的单行代码:

        return trim(preg_replace('/[^a-z0-9]+/', '-', strtolower($string)), '-');
        

        我还准备了一个演示,突出显示我认为其他答案中的不准确之处。 (Demo)

        'This, is - - the URL!' input
        'this-is-the-url'       expected
        
        'this-is-----the-url'   SilentGhost
        'this-is-the-url'       mario
        'This-is---the-URL'     Rooneyl
        'This-is-the-URL'       AbhishekGoel
        'This, is - - the URL!' HelloHack
        'This, is - - the URL!' DenisMatafonov
        'This,-is-----the-URL!' AdeelRazaAzeemi
        'this-is-the-url'       mickmackusa
        
        ---
        'Mork & Mindy'      input
        'mork-mindy'        expected
        
        'mork--mindy'       SilentGhost
        'mork-mindy'        mario
        'Mork--Mindy'       Rooneyl
        'Mork-Mindy'        AbhishekGoel
        'Mork &amp; Mindy'  HelloHack
        'Mork & Mindy'      DenisMatafonov
        'Mork-&-Mindy'      AdeelRazaAzeemi
        'mork-mindy'        mickmackusa
        
        ---
        'What the_underscore ?!?'   input
        'what-the-underscore'       expected
        
        'what-theunderscore'        SilentGhost
        'what-the_underscore'       mario
        'What-theunderscore-'       Rooneyl
        'What-theunderscore-'       AbhishekGoel
        'What the_underscore ?!?'   HelloHack
        'What the_underscore ?!?'   DenisMatafonov
        'What-the_underscore-?!?'   AdeelRazaAzeemi
        'what-the-underscore'       mickmackusa
        

        【讨论】:

          【解决方案10】:

          使用intl transliterator 是一个不错的选择,因为有了它,您可以使用一组规则轻松处理复杂的情况。我添加了自定义规则来说明它如何灵活,以及如何保留最大的有意义的信息。随意删除它们并添加您自己的规则。

          $strings = [
              'This, is - - the URL!',
              'Holmes & Yoyo',
              'L’Œil de démon',
              'How to win 1000€?',
              '€, $ & other currency symbols',
              'Und die Katze fraß alle mäuse.',
              'Белите рози на София',
              'പോണ്ടിച്ചേരി സൂര്യനു കീഴിൽ',
          ];
          
          $rules = <<<'RULES'
          # Transliteration
          :: Any-Latin ;   :: Latin-Ascii ;
          
          # examples of custom replacements
          '&' > ' and ' ;
          [^0-9][01]? { € > ' euro' ;   € > ' euros' ;
          [^0-9][01]? { '$' > ' dollar' ;   '$' > ' dollars' ;
          :: Null ;
          
          # slugify
          [^[:alnum:]&[:ascii:]]+ > '-' ;
          :: Lower ;
          
          # trim
          [$] { '-' > &Remove() ;
          '-' } [$] > &Remove() ;
          RULES;
          
          $tsl = Transliterator::createFromRules($rules, Transliterator::FORWARD);
          $results = array_map(fn($s) => $tsl->transliterate($s), $strings);
          print_r($results);
          

          demo

          不幸的是,关于 ICU 转换的 PHP 手册完全是空的,但您可以找到有关它们的信息 here

          【讨论】:

            猜你喜欢
            • 2019-08-23
            • 2010-10-19
            • 1970-01-01
            • 2017-03-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-12-15
            • 2015-12-28
            相关资源
            最近更新 更多