Como substituo espaços em branco por sublinhado e vice-versa?

221

Quero substituir o espaço em branco pelo sublinhado em uma string para criar URLs agradáveis. Então, por exemplo:

"This should be connected" becomes "This_should_be_connected" 

Eu estou usando Python com Django. Isso pode ser resolvido usando expressões regulares?

Lucas
fonte
1
Como isso pode ser alcançado no template django. Existe alguma maneira de remover espaços em branco. Existe alguma tag / filtro embutido para fazer isso? Nota: slugifynão fornece a saída desejada.
user1144616

Respostas:

374

Você não precisa de expressões regulares. O Python possui um método de string interno que faz o que você precisa:

mystring.replace(" ", "_")
rogeriopvl
fonte
29
Isso não funciona com outros caracteres de espaço em branco, como \ t ou um espaço sem quebra.
Roberto Bonvallet
12
Sim, você está correto, mas, para o propósito da pergunta, não parece necessário levar esses outros espaços em consideração.
rogeriopvl
1
preciso importar alguma coisa para que isso funcione? Eu recebo o seguinte erro: AttributeError: 'builtin_function_or_method' objeto não tem atributo 'substituir'
Ocasta Eshu 31/12
2
Provavelmente a variável que você chamou de substituir não era do tipo string.
Snigdha Batra
4
Essa resposta pode ser confusa; melhor, escreva-a como mystring = mystring.replace ("", "_"), pois ela não altera diretamente a string, mas retorna uma versão alterada.
Mehdi
79

Substituir espaços é bom, mas eu sugiro ir um pouco mais além para lidar com outros caracteres hostis à URL, como pontos de interrogação, apóstrofes, pontos de exclamação etc.

Observe também que o consenso geral entre os especialistas em SEO é que os traços são preferidos aos sublinhados nos URLs.

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!"))
Tríptico
fonte
Isto é interessante. Definitivamente vou usar este conselho.
21710 Lucas
Lembre-se de urllib.quote () a saída do seu urlify () - e se s contiver algo não-ascii?
Zgoda
1
Isso é bom - mas o primeiro ER com \ W também removerá o espaço em branco, com o resultado de que o ER subsequente não tem nada para substituir ... Se você deseja substituir seus outros caracteres por '-' entre os tokens, o primeiro ER substitui por um espaço único conforme indicado - ou seja, s = re.sub (r "\ W", '& nbsp', s) (esse pode ser um problema de formatação obscuro no StackOverflow: meta.stackexchange.com/questions/105507/… )
tiluki
2
@Triptych O que você quer dizer? Andorinha africana ou européia?
tiluki
1
Outro pequeno problema é que você remove hífens preexistentes no URL, para que, se o usuário tentasse limpar a string do URL antes de fazer o upload para ser limpo, ele seria desmarcado. Então s = re.sub (r '[^ \ w \ s-]', '', s). Pode ir um passo além e remover os espaços em branco à esquerda e à direita para que o nome do arquivo não termine ou comece com um hífen com s = re.sub (r '[^ \ w \ s-]', '', s) .strip ()
Intenex 17/07/2012
42

O Django tem uma função 'slugify' que faz isso, assim como outras otimizações amigáveis ​​à URL. Está escondido no módulo defaultfilters.

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

this-should-be-connected

Esta não é exatamente a saída solicitada, mas o IMO é melhor para uso em URLs.

Daniel Roseman
fonte
Essa é uma opção interessante, mas isso é uma questão de gosto ou quais são os benefícios do uso de hífens em vez de sublinhados. Acabei de notar que o Stackoverflow usa hífens, como você sugere. Mas digg.com, por exemplo, usa sublinhados.
21710 Lucas
Essa é a opção preferida (AFAIK). Pegue sua string, faça slugify, armazene-a em um SlugField e faça uso dela em get_absolute_url () do seu modelo. Você pode encontrar exemplos na rede facilmente.
Shanyu 17/06/09
3
As pessoas do @Lulu usam traços porque, por um longo tempo, os mecanismos de pesquisa tratavam os traços como separadores de palavras, para facilitar o processo de pesquisa com várias palavras.
James Bennett
@ Daniel Roseman, posso usar isso com variáveis ​​dinâmicas. como eu estou recebendo sites dinâmicos como cordas em um veriable
efêmera
Esta é a resposta certa. Você precisa limpar seus URLs.
Kagronick 6/05/19
40

Isso leva em conta caracteres em branco que não sejam espaço e acho que é mais rápido do que usar o remódulo:

url = "_".join( title.split() )
xOneca
fonte
4
Mais importante, ele funcionará para qualquer caractere de espaço em branco ou grupo de caracteres de espaço em branco.
dshepherd
Esta solução não lida com todos os caracteres de espaço em branco. (por exemplo \x8f)
Lokal_Profil
Boa captura, @Lokal_Profil! o documentação não especifica quais caracteres de espaço em branco são levados em consideração.
xOneca 6/12/16
1
Essa solução também não preservará delimitadores repetidos, pois split () não retorna itens vazios ao usar o comportamento padrão "split on whitespace". Ou seja, se a entrada for "olá, (6 espaços aqui) mundo"), isso resultará em "olá, _ mundo" como saída, em vez de "olá, ______ mundo".
precisa saber é o seguinte
20

Usando o remódulo:

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

A menos que você tenha vários espaços ou outras possibilidades de espaços em branco, como acima, você pode apenas usar string.replacecomo outros sugeriram.

Jarret Hardie
fonte
Obrigado, era exatamente isso que eu estava pedindo. Mas concordo que o "string.replace" parece mais adequado para minha tarefa.
21710 Lucas
Que diabos, eu pretendia votar de novo, mas, por algum motivo, ele foi rebaixado e agora meu voto está bloqueado. Desculpe Jarret.
Dave Liu
10

use o método de substituição da string:

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

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

mdirolf
fonte
6

Surpreendentemente, essa biblioteca ainda não mencionada

pacote python chamado python-slugify, que faz um bom trabalho slugifying:

pip install python-slugify

Funciona assim:

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
fonte
5

Estou usando o seguinte trecho de código para meus URLs amigáveis:

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

Também funciona bem com caracteres unicode.

Armandas
fonte
1
Você poderia explicar onde isso difere da função slugify do Django?
Andy Baker
4

O Python possui um método interno em strings chamado replace, que é usado da seguinte maneira:

string.replace(old, new)

Então você usaria:

string.replace(" ", "_")

Eu tive esse problema há algum tempo e escrevi código para substituir caracteres em uma string. Preciso começar a me lembrar de verificar a documentação do python, porque eles têm funções incorporadas para tudo.


fonte
3

O OP está usando python, mas em javascript (algo para ter cuidado, pois as sintaxes são semelhantes.

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

se você atribuir esse valor a qualquer variável, ele funcionará

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

por padrão mystring não terá isso

Rajesh
fonte
3

Você pode tentar isso:

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

Corresponder e substituir espaço> sublinhado de todos os arquivos no diretório atual


fonte