空白をアンダースコアに、またはその逆に置き換えるにはどうすればよいですか?


220

文字列の空白をアンダースコアに置き換えて、素敵なURLを作成したいと思います。したがって、たとえば:

"This should be connected" becomes "This_should_be_connected" 

DjangoでPythonを使用しています。これは正規表現を使用して解決できますか?


1
これはどのようにdjangoテンプレートで実現できますか?空白を削除する方法はありますか?これを行うための組み込みのタグ/フィルターはありますか?注:slugifyは目的の出力を提供しません。
user1144616

回答:


373

正規表現は必要ありません。Pythonには、必要なことを行う組み込みの文字列メソッドがあります。

mystring.replace(" ", "_")

29
これは、\ tや改行しないスペースなどの他の空白文字では機能しません。
Roberto Bonvallet 2009年

12
はい、あなたは正しいですが、質問の目的のために、それらの他のスペースを考慮する必要はないようです。
rogeriopvl 2009年

1
これを機能させるには何かインポートする必要がありますか?次のエラーが表示されます:AttributeError: 'builtin_function_or_method' object has no attribute 'replace'
Ocasta Eshu

2
おそらく、replaceを呼び出した変数は文字列型ではありませんでした。
Snigdha Batra 2015

4
この回答は混乱を招く可能性があります。文字列を直接変更するのではなく、変更されたバージョンを返すため、mystring = mystring.replace( ""、 "_")として記述してください。
Mehdi

79

スペースの置き換えは問題ありませんが、疑問符、アポストロフィ、感嘆符など、他の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でのフォーマットの問題のようです:meta.stackexchange.com/questions/105507/…
tiluki

2
@Triptychどういう意味ですか?アフリカやヨーロッパのツバメ?
tiluki

1
これに関するもう1つのわずかな問題は、URL内の既存のハイフンをすべて削除することです。これにより、ユーザーがアップロード前にURL文字列を削除してthis-is-cleanにしようとすると、thisiscleanに削除されます。したがって、s = re.sub(r '[^ \ w \ s-]'、 ''、s)です。ファイル名がs = re.sub(r '[^ \ w \ s-]'、 ''、s).stripのハイフンで終了または開始しないように、さらに一歩進んで先頭と末尾の空白を削除できます。 ()
Intenex

42

Djangoには、これを行う「slugify」機能と、他のURLフレンドリーな最適化があります。これはdefaultfiltersモジュールに隠されています。

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

this-should-be-connected

これは正確にあなたが求めた出力ではありませんが、IMOはURLでの使用に適しています。


これは興味深いオプションですが、これは好みの問題なのか、またはアンダースコアの代わりにハイフンを使用する利点があるのでしょうか。Stackoverflowがあなたが提案するようにハイフンを使用していることに気づきました。しかし、例えばdigg.comはアンダースコアを使用しています。
ルーカス

これはたまたま推奨されるオプションです(AFAIK)。文字列を取得し、slugifyしてSlugFieldに保存し、モデルのget_absolute_url()で使用します。ネット上で簡単に例を見つけることができます。
シャンユー

3
@Luluの人々はダッシュを使用しています。これは、長い間、検索エンジンがダッシュを単語の区切り文字として扱っていたため、複数の単語を検索する場合に、より簡単に時間をかけることができるためです。
James Bennett、

@Daniel Rosemanこれを動的変数で使用できますか?動的なWebサイトを検証可能

これが正解です。URLをサニタイズする必要があります。
kagronick

40

これはスペース以外の空白文字を考慮しており、reモジュールを使用するよりも高速だと思います:

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

4
さらに重要なのは、空白文字または空白文字のグループに対して機能することです。
dshepherd 2013年

このソリューションは、すべての空白文字を処理するわけではありません。(例\x8f
Lokal_Profil 2016

良いキャッチ、@ Lokal_Profil!ドキュメントは空白文字が考慮されている指定されていません。
xOneca 16

1
また、このソリューションでは、デフォルトの「空白で分割する」動作を使用する場合、split()は空のアイテムを返さないため、繰り返し区切り文字は保持されません。つまり、入力が「hello、(6スペースはこちら)world」の場合、出力は「hello、______ world」ではなく「hello、_world」になります。
FliesLikeABrick 2018

20

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"は私の仕事により適しているようです。
ルーカス、

一体、私はこれに賛成票を投じるつもりでしたが、何らかの理由で反対票が投じられ、今では私の投票は固定されています。申し訳ありません、ジャレット。
Dave Liu

10

文字列のreplaceメソッドを使用します。

"this should be connected".replace(" ", "_")

"this_should_be_disconnected".replace("_", " ")


6

驚いたことに、このライブラリはまだ言及されていません

python-slugifyという名前のpythonパッケージは、slugifyingのかなり良い仕事をします:

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") 

5

私のフレンドリーな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

ユニコード文字でも同様に機能します。


1
これが組み込みのDjango slugify関数とどこが違うのか説明してもらえますか?
アンディベイカー、

4

Pythonには、replaceと呼ばれる文字列の組み込みメソッドがあり、次のように使用されます。

string.replace(old, new)

だからあなたは使うでしょう:

string.replace(" ", "_")

しばらく前にこの問題があり、文字列の文字を置き換えるコードを書きました。すべての関数が組み込まれているため、Pythonのドキュメントを確認することを忘れないでください。


3

OPはPythonを使用していますが、JavaScriptで使用しています(構文は似ているため、注意が必要です)。

// only replaces the first instance of ' ' with '_'
"one two three".replace(' ', '_'); 
=> "one_two three"

// replaces all instances of ' ' with '_'
"one two three".replace(/\s/g, '_');
=> "one_two_three"

3
mystring.replace (" ", "_")

この値を任意の変数に割り当てると、機能します

s = mystring.replace (" ", "_")

デフォルトでは、mystringにはこれはありません



-3
perl -e 'map { $on=$_; s/ /_/; rename($on, $_) or warn $!; } <*>;'

スペースの一致と置換>現在のディレクトリ内のすべてのファイルの下線

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.