Làm cách nào để thay thế khoảng trắng bằng dấu gạch dưới và ngược lại?


220

Tôi muốn thay thế khoảng trắng bằng dấu gạch dưới trong một chuỗi để tạo các URL đẹp. Vì vậy, ví dụ:

"This should be connected" becomes "This_should_be_connected" 

Tôi đang sử dụng Python với Django. Điều này có thể được giải quyết bằng cách sử dụng các biểu thức thông thường?


1
Làm thế nào điều này có thể đạt được trong mẫu django. Có cách nào để loại bỏ khoảng trắng. Có bất kỳ thẻ / bộ lọc tích hợp để làm điều này? Lưu ý: slugifykhông cho đầu ra mong muốn.
dùng1144616

Câu trả lời:


373

Bạn không cần biểu thức chính quy. Python có một phương thức chuỗi dựng sẵn thực hiện những gì bạn cần:

mystring.replace(" ", "_")

29
Điều này không hoạt động với các ký tự khoảng trắng khác, chẳng hạn như \ t hoặc không gian không phá vỡ.
Roberto Bonvallet

12
Có bạn đúng, nhưng với mục đích của câu hỏi, dường như không cần thiết phải tính đến những không gian khác đó.
rogeriopvl

1
Tôi có cần nhập bất cứ thứ gì để làm việc này không? Tôi nhận được lỗi sau: AttributionError: 'buildin_feft_or_method' đối tượng không có thuộc tính 'thay thế'
Ocasta Eshu

2
Có lẽ biến mà bạn gọi là thay thế, không phải là kiểu chuỗi.
Snigdha Batra

4
Câu trả lời này có thể gây nhầm lẫn, tốt hơn nên viết nó là mystring = mystring.replace ("", "_") vì nó không trực tiếp thay đổi chuỗi mà thay vào đó trả về một phiên bản đã thay đổi.
Mehdi

79

Thay thế khoảng trắng là tốt, nhưng tôi có thể khuyên bạn nên đi xa hơn một chút để xử lý các ký tự thù địch URL khác như dấu chấm hỏi, dấu nháy đơn, dấu chấm than, v.v.

Cũng lưu ý rằng sự đồng thuận chung giữa các chuyên gia SEO là dấu gạch ngang được ưu tiên cho dấu gạch dưới trong 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!"))

Hay đấy. Tôi chắc chắn sẽ sử dụng lời khuyên này.
Lucas

Hãy nhớ urllib.quote () đầu ra của urlify () - nếu s chứa thứ gì đó không phải là ascii thì sao?
zgoda

1
Điều này thật tuyệt - nhưng RE đầu tiên với \ W cũng sẽ xóa khoảng trắng với kết quả là RE tiếp theo không có gì để thay thế ... Nếu bạn muốn thay thế các ký tự khác của mình bằng '-' giữa các token có RE đầu tiên thay thế bằng không gian duy nhất như được chỉ định - ví dụ: s = re.sub (r "\ W", '& nbsp', s) (đây có thể là sự cố định dạng mờ ám trên StackOverflow: meta.stackexchange.com/questions/105507/iêu )
tiluki

2
@Triptych Ý bạn là gì? Nuốt châu Phi hay châu Âu?
tiluki

1
Một vấn đề nhỏ khác là bạn loại bỏ bất kỳ dấu gạch ngang có sẵn nào trong url, để nếu người dùng đã cố gắng làm sạch chuỗi url trước khi tải lên để làm sạch, nó sẽ bị xóa thành lỗi này. Vậy s = re.sub (r '[^ \ w \ s-]', '', s). Có thể tiến thêm một bước và xóa khoảng trắng hàng đầu và dấu để tên tệp không kết thúc hoặc bắt đầu bằng dấu gạch nối với s = re.sub (r '[^ \ w \ s-]', '', s) .strip ()
Intenex

42

Django có chức năng 'slugify' thực hiện điều này, cũng như các tối ưu hóa thân thiện với URL khác. Nó được ẩn đi trong mô-đun defaultfilters.

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

this-should-be-connected

Đây không chính xác là đầu ra mà bạn yêu cầu, nhưng IMO sẽ tốt hơn khi sử dụng URL.


Đó là một lựa chọn thú vị, nhưng đây có phải là vấn đề của hương vị hay lợi ích của việc sử dụng dấu gạch ngang thay vì dấu gạch dưới. Tôi chỉ nhận thấy rằng Stackoverflow sử dụng dấu gạch nối như bạn đề xuất. Nhưng digg.com chẳng hạn sử dụng dấu gạch dưới.
Lucas

Điều này xảy ra là tùy chọn ưa thích (AFAIK). Lấy chuỗi của bạn, tạo chuỗi, lưu trữ chuỗi trong SlugField và sử dụng chuỗi đó trong mô hình get_absolute_url () của mô hình của bạn. Bạn có thể tìm thấy các ví dụ trên mạng một cách dễ dàng.
shanyu

3
@Lulu mọi người sử dụng dấu gạch ngang bởi vì, trong một thời gian dài, các công cụ tìm kiếm đã coi dấu gạch ngang là dấu phân cách từ và vì vậy bạn sẽ có một thời gian dễ dàng hơn trong các tìm kiếm nhiều từ.
James Bennett

@Daniel Roseman tôi có thể sử dụng điều này với biến động. khi tôi nhận được các trang web động như một chuỗi có thể kiểm chứng
phù du

Đây là câu trả lời đúng. Bạn cần vệ sinh URL của bạn.
kagronick

40

Điều này tính đến các ký tự trống ngoài không gian và tôi nghĩ nó nhanh hơn sử dụng remô-đun:

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

4
Quan trọng hơn, nó sẽ hoạt động cho bất kỳ ký tự khoảng trắng hoặc nhóm ký tự khoảng trắng.
dshepherd

Giải pháp này không xử lý tất cả các ký tự khoảng trắng. (ví dụ \x8f)
Lokal_Profil

Bắt tốt, @Lokal_Profil! Các tài liệu không xác định những ký tự khoảng trắng được đưa vào tính toán.
xOneca

1
Giải pháp này cũng sẽ không bảo toàn các dấu phân cách lặp lại, vì split () không trả về các mục trống khi sử dụng hành vi "split on whitespace" mặc định. Đó là, nếu đầu vào là "xin chào, (6 khoảng trắng ở đây) thế giới", điều này sẽ dẫn đến "xin chào, _world" là đầu ra, thay vì "xin chào, thế giới ___".
FliesLikeABrick

20

Sử dụng remô-đun:

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

Trừ khi bạn có nhiều khoảng trắng hoặc các khả năng khoảng trắng khác như trên, bạn có thể chỉ muốn sử dụng string.replacenhư những người khác đã đề xuất.


Cảm ơn bạn, đây chính xác là những gì tôi đã yêu cầu. Nhưng tôi đồng ý, "string.replace" có vẻ phù hợp hơn với nhiệm vụ của tôi.
Lucas

Cái quái gì thế, tôi có ý định nâng cấp cái này, nhưng vì một số lý do, nó đã bị hạ cấp và bây giờ phiếu bầu của tôi đã bị khóa. Xin lỗi Jarret.
Dave Liu

10

sử dụng phương thức thay thế chuỗi:

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

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


6

Đáng ngạc nhiên là thư viện này chưa được đề cập

gói python có tên python-slugify, một công việc khá tốt của slugifying:

pip install python-slugify

Hoạt động như thế này:

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

Tôi đang sử dụng đoạn mã sau cho các url thân thiện của mình:

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

Nó hoạt động tốt với các ký tự unicode là tốt.


1
Bạn có thể giải thích điều này khác với chức năng slugify Django tích hợp không?
Andy Baker

4

Python có một phương thức dựng sẵn trên các chuỗi gọi là thay thế được sử dụng như vậy:

string.replace(old, new)

Vì vậy, bạn sẽ sử dụng:

string.replace(" ", "_")

Tôi đã có vấn đề này một thời gian trước đây và tôi đã viết mã để thay thế các ký tự trong một chuỗi. Tôi phải bắt đầu nhớ kiểm tra tài liệu python vì chúng đã được tích hợp sẵn các chức năng cho mọi thứ.


3

OP đang sử dụng python, nhưng trong javascript (một điều cần cẩn thận vì các cú pháp tương tự nhau.

// 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 (" ", "_")

nếu bạn gán giá trị này cho bất kỳ biến nào, nó sẽ hoạt động

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

theo mặc định, bí ẩn sẽ không có điều này



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

Khớp et thay thế không gian> gạch dưới của tất cả các tệp trong thư mục hiện tại

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.