如何将空格替换为下划线?

309
我想在字符串中用下划线替换空格,以创建漂亮的URL。例如:
"This should be connected" 

应该变成什么

"This_should_be_connected" 

我正在使用Python和Django。这个问题能用正则表达式解决吗?


1
在Django模板中如何实现这个功能?有没有办法去除空格?是否有内置的标签/过滤器可以做到这一点?注意:slugify不能提供所需的输出。 - user1144616
14个回答

524

你不需要使用正则表达式。Python有一个内置的字符串方法可以实现你所需的功能:

mystring.replace(" ", "_")

54
这不适用于其他空白字符,比如\t或不间断空格。 - Roberto Bonvallet
15
没错,但考虑到问题的目的,似乎不必计算那些其他空间。 - rogeriopvl
2
可能你调用了replace方法的变量不是字符串类型。 - Snigdha Batra
17
这个答案可能会让人感到困惑,最好写成 mystring = mystring.replace(" ", "_") 的形式,因为它并不直接改变字符串,而是返回一个已更改的版本。 - Mehdi
5
不能与不间断空格一起使用,应改用re.sub(r"\s+", '', content) - Macbric
显示剩余3条评论

110
替换空格没问题,但我建议进一步处理其他URL不友好的字符,例如问号、撇号、感叹号等。
此外,请注意,在SEO专家中普遍共识是在URL中使用破折号比下划线更好。
import re

def urlify(s):

    # Remove all non-word characters (everything except numbers and letters)
    s = re.sub(r"[^\w\s]", '', s)

    # Replace all runs of whitespace with a single dash
    s = re.sub(r"\s+", '-', s)

    return s

# Prints: I-cant-get-no-satisfaction"
print(urlify("I can't get no satisfaction!"))

记得对 urlify() 的输出使用 urllib.quote() - 如果 s 包含非 ASCII 字符怎么办? - zgoda
1
这很好 - 但第一个带有\W的RE将同时删除空格,导致随后的RE没有任何内容可替换... 如果您想在标记之间使用“-”替换其他字符,请让第一个RE按照指示用单个空格进行替换 - 即s = re.sub(r"\W", '&nbsp', s)(这可能是StackOverflow上的格式问题:http://meta.stackexchange.com/questions/105507/how-to-add-a-space-in-the-code-section) - timlukins
@TimTheEnchanter - 好眼力。已修复。一只未负荷的燕子的空气速度是多少? - Kenan Banks
2
@Triptych 你的意思是什么?非洲燕子还是欧洲燕子? - timlukins
1
另一个小问题是您会删除URL中的任何现有连字符,因此,如果用户在上传之前尝试清理URL字符串为this-is-clean,则会被剥离为thisisclean。所以s = re.sub(r'[^\w\s-]', '', s)。可以进一步去除前导和尾随空格,以便文件名不以连字符结尾或开头,使用s = re.sub(r'[^\w\s-]', '', s).strip()。 - Intenex
显示剩余2条评论

54

这个方法考虑了除空格以外的空白字符,而且我认为它比使用re模块更快:

url = "_".join( title.split() )

4
更重要的是,它将适用于任何空白字符或一组空白字符。 - dshepherd
此解决方案无法处理所有空格字符。(例如\x8f - Lokal_Profil
很好的发现,@Lokal_Profil!文档没有指定考虑哪些空格字符。 - xOneca
1
这个解决方案也不会保留重复的分隔符,因为split()在使用默认的“按空格分割”行为时不返回空项。也就是说,如果输入是“hello,(这里有6个空格)world”,输出将是“hello,_world”,而不是“hello,______world”。 - FliesLikeABrick
2
正则表达式 > 分割/连接 > 替换 - Utku Cansever
如果您想使用1个字符替换任意数量的空格字符,那么这将非常有帮助。就像在“将所有空格减少到1个空格”的情况下一样。非常方便地从字符串中删除换行符、制表符和多个空格等。 - CodingCat

45

Django有一个名为“slugify”的函数,可以执行此操作,以及其他适合于URL的优化。它被隐藏在defaultfilters模块中。

>>> from django.template.defaultfilters import slugify
>>> slugify("This should be connected")

this-should-be-connected

这并不完全是你要求的输出,但在我看来,它更适合用于URL。


这是一个有趣的选项,但使用连字符与下划线相比有什么好处,还是只是个人口味问题?我刚刚注意到Stackoverflow使用了你建议的连字符。但例如digg.com则使用下划线。 - Lucas
这恰好是首选选项(据我所知)。将您的字符串slugify化,将其存储在SlugField中,并在模型的get_absolute_url()中使用它。 您可以轻松在网上找到示例。 - shanyu
3
人们使用破折号是因为很长一段时间以来,搜索引擎将破折号视为单词分隔符,这样在多个单词的搜索中,你就会更容易被找到。 - James Bennett
@Daniel Roseman,我能在动态变量中使用这个吗?因为我正在将动态网站作为字符串存储在一个变量中。 - ephemeral
这是正确的答案。你需要对你的URL进行清洗。 - kagronick
这不适用于utf-8字符,我用阿拉伯语测试了一下,它返回了一个空字符串""。 - Iliyass Hamza

29

使用 re 模块:

import re
re.sub('\s+', '_', "This should be connected") # This_should_be_connected
re.sub('\s+', '_', 'And     so\tshould this')  # And_so_should_this

除非你有多个空格或其他上述可能的空白字符,你可以像其他人建议的那样使用 string.replace


谢谢,这正是我所需要的。但我同意,“string.replace”似乎更适合我的任务。 - Lucas
2
PEP8将'\s+'替换为r'\s+'。详情请见:https://www.flake8rules.com/rules/W605.html - mrroot5

11

使用字符串的替换方法:

"这应该连接".replace(" ", "_")

"这_应该_断开".replace("_", " ")


9
你可以尝试使用以下方法代替:
mystring.replace(r' ','-')

这应该是正确的答案,而不是rogeriopvl的回复...他/她怎么可能得到489个赞,当它甚至都不能工作! - grepit
除了不使用下划线 - raquelhortab

7

令人惊讶的是,这个库还没有被提到过。

python-slugify是一个Python包,它对slugify做了非常好的处理:

pip install python-slugify

这是它的工作原理:
from slugify import slugify

txt = "This is a test ---"
r = slugify(txt)
self.assertEquals(r, "this-is-a-test")

txt = "This -- is a ## test ---"
r = slugify(txt)
self.assertEquals(r, "this-is-a-test")

txt = 'C\'est déjà l\'été.'
r = slugify(txt)
self.assertEquals(r, "cest-deja-lete")

txt = 'Nín hǎo. Wǒ shì zhōng guó rén'
r = slugify(txt)
self.assertEquals(r, "nin-hao-wo-shi-zhong-guo-ren")

txt = 'Компьютер'
r = slugify(txt)
self.assertEquals(r, "kompiuter")

txt = 'jaja---lol-méméméoo--a'
r = slugify(txt)
self.assertEquals(r, "jaja-lol-mememeoo-a") 

7

Python中的字符串有一个内置方法叫做replace,用法如下:

string.replace(old, new)

因此,您可以使用:

string.replace(" ", "_")

我之前遇到了这个问题,写了一些代码来替换字符串中的字符。现在我得开始记住要检查Python文档,因为它们有针对所有情况的内置函数。


5
我正在使用以下代码来生成友好的URL:

我使用以下代码来生成友好的URL:

from unicodedata import normalize
from re import sub

def slugify(title):
    name = normalize('NFKD', title).encode('ascii', 'ignore').replace(' ', '-').lower()
    #remove `other` characters
    name = sub('[^a-zA-Z0-9_-]', '', name)
    #nomalize dashes
    name = sub('-+', '-', name)

    return name

它也可以很好地处理Unicode字符。


1
你能解释一下这与内置的Django slugify函数有什么不同吗? - Andy Baker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接