2008-08-24 29 views
228

क्या है एक अच्छा पूरा regular expression या कुछ अन्य प्रक्रिया है कि शीर्षक ले जाएगा:स्टैक ओवरफ़्लो कैसे अपने एसईओ-अनुकूल यूआरएल उत्पन्न करता है?

कैसे आप स्टैक ओवरफ़्लो तरह यूआरएल का हिस्सा बनने के लिए एक शीर्षक बदल सकता हूँ?

और यह

how-do-you-change-a-title-to-be-part-of-the-url-like-stack-overflow 

कि ढेर   उफ़ान पर एसईओ के अनुकूल यूआरएल में प्रयोग किया जाता है में बदल जाते हैं?

विकास पर्यावरण जो मैं उपयोग कर रहा हूं Ruby on Rails है, लेकिन अगर कुछ अन्य प्लेटफार्म-विशिष्ट समाधान (.NET, PHP, Django) हैं, तो मुझे उनको भी देखना अच्छा लगेगा।

मुझे यकीन है कि मैं (या कोई अन्य पाठक) लाइन के नीचे एक अलग मंच पर एक ही समस्या में आ जाएगा।

मैं कस्टम मार्गों का उपयोग कर रहा हूं, और मैं मुख्य रूप से जानना चाहता हूं कि सभी विशेष पात्रों को स्ट्रिंग को कैसे बदला जाए, यह सब लोअरकेस है, और सभी व्हाइटस्पेस को प्रतिस्थापित किया गया है।

+1

[मेटा] (http://meta.stackoverflow.com) में माइग्रेट किया जाना चाहिए; चूंकि प्रश्न और उत्तर दोनों विशेष रूप से एसओ कार्यान्वयन से निपटते हैं, और स्वीकृत उत्तर @ जेफएटवुड से है। – casperOne

+19

@casperOne क्या आपको लगता है कि जेफ को कुछ गैर-मेटा प्रतिष्ठा की अनुमति नहीं है? प्रश्न "इस तरह कुछ कैसे कर सकता है" के बारे में है, विशेष रूप से "यह यहां कैसे किया जाता है"। –

+0

@ PaŭloEbermann: यह जेफ को कुछ गैर-मेटा प्रतिष्ठा प्राप्त करने के बारे में नहीं है (वह कितनी प्रतिष्ठा है वास्तव में मेरी चिंता नहीं है); प्रश्न निकाय * विशेष रूप से स्टैक ओवरफ्लो के कार्यान्वयन का संदर्भ दिया * इसलिए मेटा पर होने के लिए तर्क। – casperOne

उत्तर

266

यहां हम यह कैसे करते हैं। ध्यान दें कि पहली नज़र में आपको एहसास होने की तुलना में शायद अधिक किनारे की स्थिति है।

यह दूसरा संस्करण है, 5x अधिक प्रदर्शन के लिए अनलॉक किया गया है (और हाँ, मैंने इसे बेंचमार्क किया है)। मैंने सोचा कि मैं इसे अनुकूलित कर दूंगा क्योंकि इस फ़ंक्शन को प्रति पृष्ठ सैकड़ों बार कहा जा सकता है।

/// <summary> 
/// Produces optional, URL-friendly version of a title, "like-this-one". 
/// hand-tuned for speed, reflects performance refactoring contributed 
/// by John Gietzen (user otac0n) 
/// </summary> 
public static string URLFriendly(string title) 
{ 
    if (title == null) return ""; 

    const int maxlen = 80; 
    int len = title.Length; 
    bool prevdash = false; 
    var sb = new StringBuilder(len); 
    char c; 

    for (int i = 0; i < len; i++) 
    { 
     c = title[i]; 
     if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) 
     { 
      sb.Append(c); 
      prevdash = false; 
     } 
     else if (c >= 'A' && c <= 'Z') 
     { 
      // tricky way to convert to lowercase 
      sb.Append((char)(c | 32)); 
      prevdash = false; 
     } 
     else if (c == ' ' || c == ',' || c == '.' || c == '/' || 
      c == '\\' || c == '-' || c == '_' || c == '=') 
     { 
      if (!prevdash && sb.Length > 0) 
      { 
       sb.Append('-'); 
       prevdash = true; 
      } 
     } 
     else if ((int)c >= 128) 
     { 
      int prevlen = sb.Length; 
      sb.Append(RemapInternationalCharToAscii(c)); 
      if (prevlen != sb.Length) prevdash = false; 
     } 
     if (i == maxlen) break; 
    } 

    if (prevdash) 
     return sb.ToString().Substring(0, sb.Length - 1); 
    else 
     return sb.ToString(); 
} 

कोड इस प्रतिस्थापित के पिछले संस्करण इस पोस्ट को देखते संशोधन इतिहास को देखने के लिए (लेकिन कार्यात्मक के बराबर है, और तेजी से 5 गुना से), (तिथि लिंक पर क्लिक करें)।

इसके अलावा, RemapInternationalCharToAscii विधि स्रोत कोड here पाया जा सकता है।

+21

यह है कि न सिर्फ इतना है कि 'RemapInternationalCharToAscii()' समारोह के ठूंठ @oskar आओ जैसे उच्चारण वर्ण ड्रॉप लेकिन इसके बजाय उन्हें आओ करने के लिए deaccentuate ... ^^ –

+21

है करता है एक संस्करण के साथ अच्छा होगा वहाँ http: // मेटा। stackexchange.com/questions/7435/non-us-ascii-characters-dropped-from-full-profile-url/7696#7696 –

+3

यह बहुत अच्छा है। मैंने अभी तक केवल एक ही बदलाव किया है "अगर (i == maxlen) तोड़ना;" बनने के लिए "अगर (एसबी। लम्बाई == maxlen) तोड़;" सिर्फ मामले में स्ट्रिंग मैं में गुजर रहा हूँ। –

16

आप नियंत्रक को URL पर इंगित करने के लिए एक कस्टम मार्ग सेट करना चाहते हैं जो इसे संभालेगा। चूंकि आप रेल पर रूबी का उपयोग कर रहे हैं, इसलिए यहां उनके रूटिंग इंजन का उपयोग करने में introduction है।

रूबी में, आप यहाँ एक नियमित अभिव्यक्ति की जरूरत है जैसे आप पहले से ही पता चल जाएगा और उपयोग करने के लिए नियमित रूप से अभिव्यक्ति है:

def permalink_for(str) 
    str.gsub(/[^\w\/]|[!\(\)\.]+/, ' ').strip.downcase.gsub(/\ +/, '-') 
end 
5

मैं रूबी ऑन रेल्स से परिचित नहीं हूँ, लेकिन निम्नलिखित (untested) पीएचपी है कोड। यदि आप इसे उपयोगी पाते हैं तो आप शायद रेलवे पर रूबी को बहुत जल्दी अनुवाद कर सकते हैं।

$sURL = "This is a title to convert to URL-format. It has 1 number in it!"; 
// To lower-case 
$sURL = strtolower($sURL); 

// Replace all non-word characters with spaces 
$sURL = preg_replace("/\W+/", " ", $sURL); 

// Remove trailing spaces (so we won't end with a separator) 
$sURL = trim($sURL); 

// Replace spaces with separators (hyphens) 
$sURL = str_replace(" ", "-", $sURL); 

echo $sURL; 
// outputs: this-is-a-title-to-convert-to-url-format-it-has-1-number-in-it 

मुझे उम्मीद है कि इससे मदद मिलती है।

4

मैं रूबी या रेल के बारे में ज्यादा नहीं, लेकिन पर्ल में, यह मैं क्या कर सकता है:

my $title = "How do you change a title to be part of the url like Stackoverflow?"; 

my $url = lc $title; # Change to lower case and copy to URL. 
$url =~ s/^\s+//g;  # Remove leading spaces. 
$url =~ s/\s+$//g;  # Remove trailing spaces. 
$url =~ s/\s+/\-/g; # Change one or more spaces to single hyphen. 
$url =~ s/[^\w\-]//g; # Remove any non-word characters. 

print "$title\n$url\n"; 

मैं सिर्फ एक त्वरित परीक्षण किया था और यह काम करने लगता है। उम्मीद है कि रूबी में अनुवाद करना अपेक्षाकृत आसान है।

3

मान लिया जाये कि अपने मॉडल वर्ग एक शीर्षक विशेषता है कि, तो आप बस to_param विधि मॉडल के भीतर, ओवरराइड कर सकते हैं इस तरह:

def to_param 
    title.downcase.gsub(/ /, '-') 
end 

This Railscast episode सभी विवरण है। आप यह भी सुनिश्चित कर सकते हैं कि शीर्षक में केवल वैध वर्ण हैं:

validates_format_of :title, :with => /^[a-z0-9-]+$/, 
        :message => 'can only contain letters, numbers and hyphens' 
3

मज़ेदार पात्रों के बारे में क्या? आप उन लोगों के बारे में क्या करने जा रहे हैं? उमलॉट? विराम चिह्न? इन पर विचार करने की जरूरत है। असल में, मैं एक सफेद-सूची दृष्टिकोण का उपयोग करता हूं, जैसा उपर्युक्त ब्लैक-लिस्ट दृष्टिकोण के विपरीत है: वर्णन करें कि आप कौन से पात्रों को अनुमति देंगे, आप कौन से पात्रों को परिवर्तित करेंगे (किसके लिए?) और फिर बाकी को अर्थपूर्ण ("") में बदल दें । मुझे संदेह है कि आप इसे एक रेगेक्स में कर सकते हैं ... क्यों न केवल पात्रों के माध्यम से लूप?

2

ब्रायन की कोड, रूबी में:

title.downcase.strip.gsub(/\ /, '-').gsub(/[^\w\-]/, '') 

downcase लोअरकेस स्ट्रिंग बदल जाता है, strip को हटा प्रमुख और रिक्त स्थान को अनुगामी, पहले gsub कॉल जी lobally डैश से उप stitutes रिक्त स्थान है, और दूसरा एक पत्र या डैश नहीं है जो सब कुछ हटा देता है।

9

अच्छी माप के लिए, यहां वर्डप्रेस में PHP फ़ंक्शन है जो ऐसा करता है ... मुझे लगता है कि वर्डप्रेस फैंसी लिंक का उपयोग करने वाले अधिक लोकप्रिय प्लेटफार्मों में से एक है।

 
    function sanitize_title_with_dashes($title) { 
      $title = strip_tags($title); 
      // Preserve escaped octets. 
      $title = preg_replace('|%([a-fA-F0-9][a-fA-F0-9])|', '---$1---', $title); 
      // Remove percent signs that are not part of an octet. 
      $title = str_replace('%', '', $title); 
      // Restore octets. 
      $title = preg_replace('|---([a-fA-F0-9][a-fA-F0-9])---|', '%$1', $title); 
      $title = remove_accents($title); 
      if (seems_utf8($title)) { 
        if (function_exists('mb_strtolower')) { 
          $title = mb_strtolower($title, 'UTF-8'); 
        } 
        $title = utf8_uri_encode($title, 200); 
      } 
      $title = strtolower($title); 
      $title = preg_replace('/&.+?;/', '', $title); // kill entities 
      $title = preg_replace('/[^%a-z0-9 _-]/', '', $title); 
      $title = preg_replace('/\s+/', '-', $title); 
      $title = preg_replace('|-+|', '-', $title); 
      $title = trim($title, '-'); 
      return $title; 
    } 

यह फ़ंक्शन के साथ-साथ कुछ सहायक कार्यों को wp-include/formatting.php में पाया जा सकता है।

+5

यह पूर्ण उत्तर नहीं है। आप इस तरह के कार्यों को याद कर रहे हैं: 'remove_accents',' seem_utf8' ... –

+0

@ द हाउ टू गीक जवाब को पूरा करने के लिए आप अभी भी क्लोन गिट को गिट कर सकते हैं: // core.git.wordpress.org/'और 'wp – mickro

2

PermalinkFu नामक रेल प्लगइन पर एक छोटी रूबी है, जो ऐसा करता है। escape method एक स्ट्रिंग में परिवर्तन करता है जो URL के लिए उपयुक्त है। कोड पर एक नज़र डालें; वह विधि काफी सरल है।

गैर-ASCII अक्षरों को हटाने के लिए यह 'utcii_' से 'ascii // ignore // translit' में अनुवाद करने के लिए iconv lib का उपयोग करता है। रिक्त स्थान तो डैश में बदल रहे हैं, सब कुछ downcased है, आदि

+0

में शामिल/formatting.php' फ़ाइल शामिल है, जबकि यह पूरी तरह से काम करता है, मुझे लगता है कि यह बहुत ही कुशल नहीं है। – WhyNotHugo

11

तुम भी स्लग के में फार्म पीढ़ी के लिए इस JavaScript फ़ंक्शन का उपयोग कर सकते हैं (पर यह एक आधारित है/Django से नकल):

function makeSlug(urlString, filter) { 
    // Changes, e.g., "Petty theft" to "petty_theft". 
    // Remove all these words from the string before URLifying 

    if(filter) { 
     removelist = ["a", "an", "as", "at", "before", "but", "by", "for", "from", 
     "is", "in", "into", "like", "of", "off", "on", "onto", "per", 
     "since", "than", "the", "this", "that", "to", "up", "via", "het", "de", "een", "en", 
     "with"]; 
    } 
    else { 
     removelist = []; 
    } 
    s = urlString; 
    r = new RegExp('\\b(' + removelist.join('|') + ')\\b', 'gi'); 
    s = s.replace(r, ''); 
    s = s.replace(/[^-\w\s]/g, ''); // Remove unneeded characters 
    s = s.replace(/^\s+|\s+$/g, ''); // Trim leading/trailing spaces 
    s = s.replace(/[-\s]+/g, '-'); // Convert spaces to hyphens 
    s = s.toLowerCase(); // Convert to lowercase 
    return s; // Trim to first num_chars characters 
} 
4

T-SQL कार्यान्वयन, dbo.UrlEncode से अनुकूलित:

CREATE FUNCTION dbo.Slug(@string varchar(1024)) 
RETURNS varchar(3072) 
AS 
BEGIN 
    DECLARE @count int, @c char(1), @i int, @slug varchar(3072) 

    SET @string = replace(lower(ltrim(rtrim(@string))),' ','-') 

    SET @count = Len(@string) 
    SET @i = 1 
    SET @slug = '' 

    WHILE (@i <= @count) 
    BEGIN 
     SET @c = substring(@string, @i, 1) 

     IF @c LIKE '[a-z0-9--]' 
      SET @slug = @slug + @c 

     SET @i = @i +1 
    END 

    RETURN @slug 
END 
5

आप रेल में बढ़त का उपयोग कर रहे हैं, तो आप Inflector.parametrize पर भरोसा कर सकते - यहाँ प्रलेखन से उदाहरण है:

class Person 
    def to_param 
     "#{id}-#{name.parameterize}" 
    end 
    end 

    @person = Person.find(1) 
    # => #<Person id: 1, name: "Donald E. Knuth"> 

    <%= link_to(@person.name, person_path(@person)) %> 
    # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a> 

इसके अलावा, आप रेल के पिछले संस्करण में इस तरह के लहजे (éphémère) के रूप में और अधिक विदेशी पात्रों को संभालने के लिए जरूरत है, आप PermalinkFu और DiacriticsFu के मिश्रण का उपयोग कर सकते हैं:

DiacriticsFu::escape("éphémère") 
=> "ephemere" 

DiacriticsFu::escape("räksmörgås") 
=> "raksmorgas" 
-1

नहीं, नहीं, नहीं। आप सब बहुत गलत हैं। Diacritics-fu सामान को छोड़कर, आप वहां जा रहे हैं, लेकिन एशियाई पात्रों के बारे में क्या (रुबी डेवलपर्स पर शर्मिंदा उनके nihonjin भाइयों पर विचार नहीं करने के लिए)।

फ़ायरफ़ॉक्स और सफारी दोनों URL में गैर-ASCII वर्ण प्रदर्शित करते हैं, और स्पष्ट रूप से वे बहुत अच्छे लगते हैं। 'http://somewhere.com/news/read/お前たちはアホじゃないかい' जैसे लिंक का समर्थन करना अच्छा होता है।

तो यहां कुछ PHP कोड है जो यह करेंगे, लेकिन मैंने अभी इसे लिखा है और तनाव का परीक्षण नहीं किया है।

<?php 
    function slug($str) 
    { 
     $args = func_get_args(); 
     array_filter($args); //remove blanks 
     $slug = mb_strtolower(implode('-', $args)); 

     $real_slug = ''; 
     $hyphen = ''; 
     foreach(SU::mb_str_split($slug) as $c) 
     { 
      if (strlen($c) > 1 && mb_strlen($c)===1) 
      { 
       $real_slug .= $hyphen . $c; 
       $hyphen = ''; 
      } 
      else 
      { 
       switch($c) 
       { 
        case '&': 
         $hyphen = $real_slug ? '-and-' : ''; 
         break; 
        case 'a': 
        case 'b': 
        case 'c': 
        case 'd': 
        case 'e': 
        case 'f': 
        case 'g': 
        case 'h': 
        case 'i': 
        case 'j': 
        case 'k': 
        case 'l': 
        case 'm': 
        case 'n': 
        case 'o': 
        case 'p': 
        case 'q': 
        case 'r': 
        case 's': 
        case 't': 
        case 'u': 
        case 'v': 
        case 'w': 
        case 'x': 
        case 'y': 
        case 'z': 

        case 'A': 
        case 'B': 
        case 'C': 
        case 'D': 
        case 'E': 
        case 'F': 
        case 'G': 
        case 'H': 
        case 'I': 
        case 'J': 
        case 'K': 
        case 'L': 
        case 'M': 
        case 'N': 
        case 'O': 
        case 'P': 
        case 'Q': 
        case 'R': 
        case 'S': 
        case 'T': 
        case 'U': 
        case 'V': 
        case 'W': 
        case 'X': 
        case 'Y': 
        case 'Z': 

        case '0': 
        case '1': 
        case '2': 
        case '3': 
        case '4': 
        case '5': 
        case '6': 
        case '7': 
        case '8': 
        case '9': 
         $real_slug .= $hyphen . $c; 
         $hyphen = ''; 
         break; 

        default: 
         $hyphen = $hyphen ? $hyphen : ($real_slug ? '-' : ''); 
       } 
      } 
     } 
     return $real_slug; 
    } 

उदाहरण:

$str = "[email protected]#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04 コリン [email protected]#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04 トーマス [email protected]#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04 アーノルド [email protected]#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04"; 
echo slug($str); 

आउटपुट: コ リ ン -और- ト ー マ ス -और- ア ー ノ ル ド

क्योंकि & -और- के लिए बदल जाओ '

' -और- 'है '।

+3

मैं वास्तव में नहीं जानता कि जानकारी के इस टुकड़े के बारे में क्या कहना है। – sjas

+3

स्विच केस स्टेटमेंट का उपयोग न करने का यह वास्तव में एक अच्छा उदाहरण है। – NickG

28

यहां जेफ के कोड का मेरा संस्करण है। मैंने निम्नलिखित परिवर्तन किए हैं:

  • हाइफ़न इस तरह से जोड़े गए थे कि किसी को जोड़ा जा सकता है, और फिर स्ट्रिंग में अंतिम वर्ण होने के बाद इसे हटाने की आवश्यकता है। यही है, हम कभी भी "मेरा-स्लग-" नहीं चाहते हैं। इसका मतलब है कि इस एज केस पर इसे हटाने के लिए एक अतिरिक्त स्ट्रिंग आवंटन। मैंने देरी-हाइफेनिंग के द्वारा इस पर काम किया है। यदि आप जेफ के तर्क के लिए मेरे कोड की तुलना करते हैं तो इसका पालन करना आसान है।
  • उनका दृष्टिकोण पूरी तरह से लुकअप आधारित है और स्टैक   ओवरफ़्लो पर शोध करते समय उदाहरणों में मुझे मिले कई पात्रों को याद किया गया है। इसका मुकाबला करने के लिए, मैंने पहले एक सामान्यीकरण पास (मेटा स्टैक ओवरफ्लो प्रश्न Non US-ASCII characters dropped from full (profile) URL) में उल्लिखित एकेए संयोजन को स्वीकार्य किया, और फिर स्वीकार्य श्रेणियों के बाहर किसी भी वर्ण को अनदेखा कर दिया। यह ज्यादातर समय काम करता है ...
  • ... जब मुझे यह एक लुकअप टेबल भी नहीं जोड़ना पड़ता है। जैसा ऊपर बताया गया है, कुछ वर्ण सामान्य होने पर कम ASCII मान पर मैप नहीं करते हैं। इन्हें छोड़ने के बजाय मुझे अपवादों की एक मैन्युअल सूची मिली है जो छेद से भरा हुआ है, लेकिन यह कुछ भी नहीं है। सामान्यीकरण कोड स्टैक ओवरफ्लो प्रश्न How can I remove accents on a string? में जॉन हन्ना की महान पोस्ट से प्रेरित था।
  • केस रूपांतरण अब भी वैकल्पिक है।

    public static class Slug 
    { 
        public static string Create(bool toLower, params string[] values) 
        { 
         return Create(toLower, String.Join("-", values)); 
        } 
    
        /// <summary> 
        /// Creates a slug. 
        /// References: 
        /// http://www.unicode.org/reports/tr15/tr15-34.html 
        /// https://meta.stackexchange.com/questions/7435/non-us-ascii-characters-dropped-from-full-profile-url/7696#7696 
        /// https://stackoverflow.com/questions/25259/how-do-you-include-a-webpage-title-as-part-of-a-webpage-url/25486#25486 
        /// https://stackoverflow.com/questions/3769457/how-can-i-remove-accents-on-a-string 
        /// </summary> 
        /// <param name="toLower"></param> 
        /// <param name="normalised"></param> 
        /// <returns></returns> 
        public static string Create(bool toLower, string value) 
        { 
         if (value == null) 
          return ""; 
    
         var normalised = value.Normalize(NormalizationForm.FormKD); 
    
         const int maxlen = 80; 
         int len = normalised.Length; 
         bool prevDash = false; 
         var sb = new StringBuilder(len); 
         char c; 
    
         for (int i = 0; i < len; i++) 
         { 
          c = normalised[i]; 
          if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) 
          { 
           if (prevDash) 
           { 
            sb.Append('-'); 
            prevDash = false; 
           } 
           sb.Append(c); 
          } 
          else if (c >= 'A' && c <= 'Z') 
          { 
           if (prevDash) 
           { 
            sb.Append('-'); 
            prevDash = false; 
           } 
           // Tricky way to convert to lowercase 
           if (toLower) 
            sb.Append((char)(c | 32)); 
           else 
            sb.Append(c); 
          } 
          else if (c == ' ' || c == ',' || c == '.' || c == '/' || c == '\\' || c == '-' || c == '_' || c == '=') 
          { 
           if (!prevDash && sb.Length > 0) 
           { 
            prevDash = true; 
           } 
          } 
          else 
          { 
           string swap = ConvertEdgeCases(c, toLower); 
    
           if (swap != null) 
           { 
            if (prevDash) 
            { 
             sb.Append('-'); 
             prevDash = false; 
            } 
            sb.Append(swap); 
           } 
          } 
    
          if (sb.Length == maxlen) 
           break; 
         } 
         return sb.ToString(); 
        } 
    
        static string ConvertEdgeCases(char c, bool toLower) 
        { 
         string swap = null; 
         switch (c) 
         { 
          case 'ı': 
           swap = "i"; 
           break; 
          case 'ł': 
           swap = "l"; 
           break; 
          case 'Ł': 
           swap = toLower ? "l" : "L"; 
           break; 
          case 'đ': 
           swap = "d"; 
           break; 
          case 'ß': 
           swap = "ss"; 
           break; 
          case 'ø': 
           swap = "o"; 
           break; 
          case 'Þ': 
           swap = "th"; 
           break; 
         } 
         return swap; 
        } 
    } 
    

अधिक जानकारी के लिए, इकाई परीक्षण, और क्यों Facebook के URL योजना ढेर Overflows की तुलना में थोड़ा होशियार है की एक विवरण, मैं एक expanded version of this on my blog मिल गया है।

+3

+1 यह महान दान है। मैंने संभवतः 'अगर (i == maxlen) ब्रेक को बदलने के बारे में आपके ब्लॉग पर एक टिप्पणी भी जोड़ दी है,' अगर (एसबी। लम्बाई == maxlen) तोड़ें; 'इसके बजाय यदि आप बहुत से स्ट्रिंग में पास करते हैं व्हाइटस्पेस/अमान्य वर्णों को आप अभी भी वांछित लंबाई का एक स्लग प्राप्त कर सकते हैं, जबकि कोड के रूप में यह खड़ा हो सकता है, इसे बड़े पैमाने पर छोटा कर सकता है (उदाहरण के लिए उस मामले पर विचार करें जहां आप 80 रिक्त स्थान से शुरू करते हैं ...)। और जेफ के कोड के खिलाफ 10,000,000 पुनरावृत्तियों के एक मोटे बेंचमार्क ने यह लगभग उसी गति के रूप में दिखाया। –

+0

धन्यवाद, मेरे ब्लॉग पर जवाब दिया और वह वहां और ऊपर कोड तय किया। कोड बेंचमार्किंग के लिए भी धन्यवाद। रुचि रखने वालों के लिए यह जेफ के बराबर था। – DanH

+0

यह अच्छा है। धन्यवाद दान! –

2

आप निम्न सहायक विधि का उपयोग कर सकते हैं। यह यूनिकोड वर्णों को परिवर्तित कर सकता है।

public static string ConvertTextToSlug(string s) 
{ 
    StringBuilder sb = new StringBuilder(); 

    bool wasHyphen = true; 

    foreach (char c in s) 
    { 
     if (char.IsLetterOrDigit(c)) 
     { 
      sb.Append(char.ToLower(c)); 
      wasHyphen = false; 
     } 
     else 
      if (char.IsWhiteSpace(c) && !wasHyphen) 
      { 
       sb.Append('-'); 
       wasHyphen = true; 
      } 
    } 

    // Avoid trailing hyphens 
    if (wasHyphen && sb.Length > 0) 
     sb.Length--; 

    return sb.ToString().Replace("--","-"); 
} 
1

मुझे regular expressions का उपयोग किये बिना यह तरीका पसंद आया, इसलिए मैंने इसे PHP पर पोर्ट किया।मैं सिर्फ एक समारोह पात्रों की जांच करने के is_between बुलाया कहा:

function is_between($val, $min, $max) 
{ 
    $val = (int) $val; $min = (int) $min; $max = (int) $max; 

    return ($val >= $min && $val <= $max); 
} 

function international_char_to_ascii($char) 
{ 
    if (mb_strpos('àåáâäãåa', $char) !== false) 
    { 
     return 'a'; 
    } 

    if (mb_strpos('èéêëe', $char) !== false) 
    { 
     return 'e'; 
    } 

    if (mb_strpos('ìíîïi', $char) !== false) 
    { 
     return 'i'; 
    } 

    if (mb_strpos('òóôõö', $char) !== false) 
    { 
     return 'o'; 
    } 

    if (mb_strpos('ùúûüuu', $char) !== false) 
    { 
     return 'u'; 
    } 

    if (mb_strpos('çccc', $char) !== false) 
    { 
     return 'c'; 
    } 

    if (mb_strpos('zzž', $char) !== false) 
    { 
     return 'z'; 
    } 

    if (mb_strpos('ssšs', $char) !== false) 
    { 
     return 's'; 
    } 

    if (mb_strpos('ñn', $char) !== false) 
    { 
     return 'n'; 
    } 

    if (mb_strpos('ýÿ', $char) !== false) 
    { 
     return 'y'; 
    } 

    if (mb_strpos('gg', $char) !== false) 
    { 
     return 'g'; 
    } 

    if (mb_strpos('r', $char) !== false) 
    { 
     return 'r'; 
    } 

    if (mb_strpos('l', $char) !== false) 
    { 
     return 'l'; 
    } 

    if (mb_strpos('d', $char) !== false) 
    { 
     return 'd'; 
    } 

    if (mb_strpos('ß', $char) !== false) 
    { 
     return 'ss'; 
    } 

    if (mb_strpos('Þ', $char) !== false) 
    { 
     return 'th'; 
    } 

    if (mb_strpos('h', $char) !== false) 
    { 
     return 'h'; 
    } 

    if (mb_strpos('j', $char) !== false) 
    { 
     return 'j'; 
    } 
    return ''; 
} 

function url_friendly_title($url_title) 
{ 
    if (empty($url_title)) 
    { 
     return ''; 
    } 

    $url_title = mb_strtolower($url_title); 

    $url_title_max_length = 80; 
    $url_title_length  = mb_strlen($url_title); 
    $url_title_friendly  = ''; 
    $url_title_dash_added = false; 
    $url_title_char = ''; 

    for ($i = 0; $i < $url_title_length; $i++) 
    { 
     $url_title_char  = mb_substr($url_title, $i, 1); 

     if (strlen($url_title_char) == 2) 
     { 
      $url_title_ascii = ord($url_title_char[0]) * 256 + ord($url_title_char[1]) . "\r\n"; 
     } 
     else 
     { 
      $url_title_ascii = ord($url_title_char); 
     } 

     if (is_between($url_title_ascii, 97, 122) || is_between($url_title_ascii, 48, 57)) 
     { 
      $url_title_friendly .= $url_title_char; 

      $url_title_dash_added = false; 
     } 
     elseif(is_between($url_title_ascii, 65, 90)) 
     { 
      $url_title_friendly .= chr(($url_title_ascii | 32)); 

      $url_title_dash_added = false; 
     } 
     elseif($url_title_ascii == 32 || $url_title_ascii == 44 || $url_title_ascii == 46 || $url_title_ascii == 47 || $url_title_ascii == 92 || $url_title_ascii == 45 || $url_title_ascii == 47 || $url_title_ascii == 95 || $url_title_ascii == 61) 
     { 
      if (!$url_title_dash_added && mb_strlen($url_title_friendly) > 0) 
      { 
       $url_title_friendly .= chr(45); 

       $url_title_dash_added = true; 
      } 
     } 
     else if ($url_title_ascii >= 128) 
     { 
      $url_title_previous_length = mb_strlen($url_title_friendly); 

      $url_title_friendly .= international_char_to_ascii($url_title_char); 

      if ($url_title_previous_length != mb_strlen($url_title_friendly)) 
      { 
       $url_title_dash_added = false; 
      } 
     } 

     if ($i == $url_title_max_length) 
     { 
      break; 
     } 
    } 

    if ($url_title_dash_added) 
    { 
     return mb_substr($url_title_friendly, 0, -1); 
    } 
    else 
    { 
     return $url_title_friendly; 
    } 
} 
2

stackoverflow solution (हमेशा की तरह, आईई को छोड़कर) महान है, लेकिन आधुनिक ब्राउज़र अब अच्छी तरह से UTF8 एन्कोडिंग संभाल:

enter image description here

तो मैं उन्नत बनाया प्रस्तावित समाधान:

public static string ToFriendlyUrl(string title, bool useUTF8Encoding = false) 
{ 
    ... 

     else if (c >= 128) 
     { 
      int prevlen = sb.Length; 
      if (useUTF8Encoding) 
      { 
       sb.Append(HttpUtility.UrlEncode(c.ToString(CultureInfo.InvariantCulture),Encoding.UTF8)); 
      } 
      else 
      { 
       sb.Append(RemapInternationalCharToAscii(c)); 
      } 
    ... 
} 

Full Code on Pastebin

संपादित करें: Here's the codeRemapInternationalCharToAscii विधि (जो पेस्टबिन में गायब है) के लिए।

+0

[विकिपीडिया] के अनुसार (http://en.wikipedia.org/wiki/Internationalized_domain_name), मोज़िला 1.4, नेटस्केप 7.1, ओपेरा 7.11 आईडीएनए का समर्थन करने वाले पहले अनुप्रयोगों में से एक थे। आईडीएन समर्थन प्रदान करने के लिए इंटरनेट एक्सप्लोरर 6 के लिए ब्राउज़र प्लगइन उपलब्ध है। इंटरनेट एक्सप्लोरर 7.0 और विंडोज विस्टा के यूआरएल एपीआई आईडीएन के लिए मूल समर्थन प्रदान करते हैं। यूटीएफ -8 अक्षरों को हटाने की तरह लगता है कि समय बर्बाद है। लंबे समय तक यूटीएफ -8 रहो !!! –

2

यहाँ मेरी (धीमी है, लेकिन मज़ा लिखने के लिए) जेफ के कोड का संस्करण है:

public static string URLFriendly(string title) 
{ 
    char? prevRead = null, 
     prevWritten = null; 

    var seq = 
     from c in title 
     let norm = RemapInternationalCharToAscii(char.ToLowerInvariant(c).ToString())[0] 
     let keep = char.IsLetterOrDigit(norm) 
     where prevRead.HasValue || keep 
     let replaced = keep ? norm 
      : prevWritten != '-' ? '-' 
      : (char?)null 
     where replaced != null 
     let s = replaced + (prevRead == null ? "" 
      : norm == '#' && "cf".Contains(prevRead.Value) ? "sharp" 
      : norm == '+' ? "plus" 
      : "") 
     let _ = prevRead = norm 
     from written in s 
     let __ = prevWritten = written 
     select written; 

    const int maxlen = 80; 
    return string.Concat(seq.Take(maxlen)).TrimEnd('-'); 
} 

public static string RemapInternationalCharToAscii(string text) 
{ 
    var seq = text.Normalize(NormalizationForm.FormD) 
     .Where(c => CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark); 

    return string.Concat(seq).Normalize(NormalizationForm.FormC); 
} 

मेरा परीक्षण स्ट्रिंग:

" I love C#, F#, C++, and... Crème brûlée!!! They see me codin'... they hatin'... tryin' to catch me codin' dirty... "

1

अब सभी ब्राउज़र अच्छी तरह से UTF8 एन्कोडिंग संभाल, तो आप कर सकते हैं WebUtility.UrlEncode विधि का उपयोग करें, इसकी तरह HttpUtility.UrlEncode @giamin द्वारा उपयोग की जाती है लेकिन इसका कार्य किसी वेब एप्लिकेशन के बाहर होता है।

3

मैं जानता हूँ कि यह बहुत पुराना सवाल है लेकिन ब्राउज़रों के सबसे बाद से अब समर्थन यूनिकोड यूआरएल मैं XRegex कि पत्र के अलावा सब कुछ बदल देता है में एक महान समाधान (सभी भाषाओं में करने के लिए '-')।

यह कई प्रोग्रामिंग भाषाओं में किया जा सकता है।

पैटर्न \\p{^L}+ है और फिर आपको सभी गैर अक्षरों को '-' में बदलने के लिए इसका उपयोग करने की आवश्यकता है।

xregex मॉड्यूल के साथ node.js में कार्य उदाहरण।

var text = 'This ! can @ have # several $ letters % from different languages such as עברית or Español'; 

var slugRegEx = XRegExp('((?!\\d)\\p{^L})+', 'g'); 

var slug = XRegExp.replace(text, slugRegEx, '-').toLowerCase(); 

console.log(slug) ==> "this-can-have-several-letters-from-different-languages-such-as-עברית-or-español" 
संबंधित मुद्दे