Bagaimana cara mengganti spasi putih dengan garis bawah dan sebaliknya?

221

Saya ingin mengganti spasi dengan garis bawah dalam string untuk membuat URL yang bagus. Jadi misalnya:

"This should be connected" becomes "This_should_be_connected" 

Saya menggunakan Python dengan Django. Bisakah ini diselesaikan dengan menggunakan ekspresi reguler?

Lucas
sumber
1
Bagaimana ini bisa dicapai dalam template Django. Apakah ada cara untuk menghilangkan spasi putih? Apakah ada tag / filter bawaan untuk melakukan ini? Catatan: slugifytidak memberikan output yang diinginkan.
user1144616

Jawaban:

374

Anda tidak perlu ekspresi reguler. Python memiliki metode string bawaan yang melakukan apa yang Anda butuhkan:

mystring.replace(" ", "_")
rogeriopvl
sumber
29
Ini tidak berfungsi dengan karakter spasi putih lain, seperti \ t atau ruang tanpa putus.
Roberto Bonvallet
12
Ya, Anda benar, tetapi untuk keperluan pertanyaan yang diajukan, tampaknya tidak perlu memperhitungkan ruang-ruang lain itu.
rogeriopvl
1
apakah saya perlu mengimpor sesuatu agar ini berfungsi? Saya mendapatkan kesalahan berikut: AttributeError: objek 'builtin_function_or_method' tidak memiliki atribut 'ganti'
Ocasta Eshu
2
Mungkin variabel yang Anda panggil ganti, bukan tipe string.
Snigdha Batra
4
Jawaban ini bisa membingungkan, lebih baik tuliskan sebagai mystring = mystring.replace ("", "_") karena tidak secara langsung mengubah string tetapi mengembalikan versi yang diubah.
Mehdi
79

Mengganti spasi baik-baik saja, tetapi saya mungkin menyarankan untuk sedikit lebih jauh menangani karakter URL-bermusuhan lainnya seperti tanda tanya, apostrof, poin seru, dll.

Perhatikan juga bahwa konsensus umum di antara para pakar SEO adalah bahwa tanda hubung lebih disukai daripada garis bawah pada 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!"))
Triptych
sumber
Ini menarik. Saya pasti akan menggunakan saran ini.
Lucas
Ingatlah untuk urllib.quote () output dari urlify Anda () - bagaimana jika s berisi sesuatu yang non-ascii?
zgoda
1
Ini bagus - tetapi RE pertama dengan \ W juga akan menghapus spasi dengan hasil bahwa RE berikutnya tidak ada yang perlu diganti ... Jika Anda ingin mengganti karakter lain dengan '-' di antara token, RE yang pertama ganti dengan yang satu ruang seperti yang ditunjukkan - yaitu s = re.sub (r "\ W", '& nbsp', s) (ini mungkin masalah pemformatan shonky pada StackOverflow: meta.stackexchange.com/questions/105507/… )
tiluki
2
@ Triptych Apa maksudmu? Menelan Afrika atau Eropa?
tiluki
1
Masalah kecil lain dengan ini adalah Anda menghapus tanda hubung yang sudah ada sebelumnya di url, sehingga jika pengguna telah mencoba untuk membersihkan string url sebelum mengunggah ke ini-ini-bersih, itu akan dilucuti ke bersih ini. Jadi s = re.sub (r '[^ \ w \ s-]', '', s). Dapat melangkah lebih jauh dan menghapus spasi spasi awal dan akhir agar nama file tidak diakhiri atau dimulai dengan tanda hubung dengan s = re.sub (r '[^ \ w \ s-]', '', s) .strip ()
Intenex
42

Django memiliki fungsi 'slugify' yang melakukan hal ini, serta optimisasi ramah URL lainnya. Tersembunyi di modul defaultfilters.

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

this-should-be-connected

Ini bukan output yang Anda minta, tetapi IMO lebih baik untuk digunakan dalam URL.

Daniel Roseman
sumber
Itu adalah pilihan yang menarik, tetapi apakah ini masalah selera atau apa manfaat menggunakan tanda hubung daripada menggarisbawahi. Saya hanya memperhatikan bahwa Stackoverflow menggunakan tanda hubung seperti yang Anda sarankan. Namun digg.com misalnya menggunakan garis bawah.
Lucas
Ini kebetulan merupakan opsi yang lebih disukai (AFAIK). Ambil string Anda, slugify, simpan di SlugField, dan gunakan di get_absolute_url () model Anda. Anda dapat menemukan contoh di internet dengan mudah.
shanyu
3
@Lulu orang menggunakan tanda hubung karena, untuk waktu yang lama, mesin pencari memperlakukan tanda hubung sebagai pemisah kata sehingga Anda akan mendapatkan waktu yang lebih mudah untuk muncul dalam pencarian multi-kata.
James Bennett
@ Daniel Roseman dapatkah saya menggunakan ini dengan variabel dinamis. karena saya mendapatkan situs web dinamis sebagai string dalam veriable
ephemeral
Ini adalah jawaban yang benar. Anda perlu membersihkan URL Anda.
kagronick
40

Ini memperhitungkan karakter kosong akun selain spasi dan saya pikir ini lebih cepat daripada menggunakan remodul:

url = "_".join( title.split() )
xOneca
sumber
4
Lebih penting lagi itu akan berfungsi untuk karakter spasi putih atau grup karakter spasi putih.
dshepherd
Solusi ini tidak menangani semua karakter spasi putih. (mis. \x8f)
Lokal_Profil
Tangkapan yang bagus, @Lokal_Profil! The dokumentasi tidak menentukan karakter spasi diperhitungkan.
xOneca
1
Solusi ini juga tidak akan mempertahankan pembatas berulang, karena split () tidak mengembalikan item kosong saat menggunakan perilaku "split on whitespace" default. Yaitu, jika inputnya adalah "halo, (6 spasi di sini) dunia", ini akan menghasilkan "halo, dunia _" sebagai output, bukan "halo, ______ dunia".
FliesLikeABrick
20

Menggunakan remodul:

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

Kecuali jika Anda memiliki beberapa ruang atau kemungkinan spasi putih seperti di atas, Anda mungkin hanya ingin menggunakan string.replaceseperti yang disarankan orang lain.

Jarret Hardie
sumber
Terima kasih, inilah tepatnya yang saya minta. Tapi saya setuju, "string.replace" tampaknya lebih cocok untuk tugas saya.
Lucas
Apa-apaan ini, maksudku untuk mengungguli ini, tetapi untuk beberapa alasan itu dibatalkan dan sekarang suaraku terkunci. Maaf Jarret.
Dave Liu
10

gunakan metode ganti string:

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

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

mdirolf
sumber
6

Anehnya perpustakaan ini belum disebutkan

Paket python bernama python-slugify, yang melakukan pekerjaan slugifying dengan cukup baik:

pip install python-slugify

Bekerja seperti ini:

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") 
Yash
sumber
5

Saya menggunakan potongan kode berikut untuk url ramah saya:

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

Ini berfungsi dengan baik dengan karakter unicode juga.

Armanda
sumber
1
Bisakah Anda menjelaskan di mana ini berbeda dari fungsi slugify Django bawaan?
Andy Baker
4

Python memiliki metode bawaan pada string yang disebut replace yang digunakan sebagai berikut:

string.replace(old, new)

Jadi, Anda akan menggunakan:

string.replace(" ", "_")

Saya punya masalah ini beberapa waktu yang lalu dan saya menulis kode untuk mengganti karakter dalam sebuah string. Saya harus mulai mengingat untuk memeriksa dokumentasi python karena mereka memiliki fungsi bawaan untuk semuanya.


sumber
3

OP menggunakan python, tetapi dalam javascript (sesuatu yang harus diperhatikan karena sintaksinya mirip.

// 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"
twmulloy
sumber
3
mystring.replace (" ", "_")

jika Anda menetapkan nilai ini ke variabel apa pun, itu akan berfungsi

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

secara default mystring tidak akan memiliki ini

Rajesh
sumber
3

Anda dapat mencoba ini sebagai gantinya:

mystring.replace(r' ','-')
Meghaa Yadav
sumber
-3
perl -e 'map { $on=$_; s/ /_/; rename($on, $_) or warn $!; } <*>;'

Cocokkan dan ganti ruang> garis bawah semua file dalam direktori saat ini


sumber