Substituir uma string em todas as postagens

:bookmark: This guide explains how to replace a string in all posts within a Discourse instance.

:person_raising_hand: Required user level: System Administrator

:warning: Console Access Required

Want to replace a string in all the posts on a site? Let’s get started!

:warning: WARNING: We strongly recommend you take a full backup before proceeding, and make sure your string replacement is specific enough to affect only the places you want it to. If this string replacement goes wrong, every post on your site will look broken!

Access your site

Start by accessing your Discourse instance via SSH and entering the Docker container:

cd /var/discourse
./launcher enter app

Performing string replacements

Basic case-sensitive replacement

To replace a string, use the following command. Replace find with the string to locate and replace with the desired substitution:

rake 'posts:remap[find,replace]'

Example results:

find —> replace
Find —> Find
FIND —> FIND
finders keepers —> replaceers keepers
finding —> replaceing

This method can be useful for tasks such as replacing emojis:

rake 'posts:remap[:slightly_smiling:,:slight_smile:]'

The above command will replace all occurrences of :slightly_smiling: with :slight_smile:.

Case-insensitive replacement

For replacements that ignore case sensitivity use:

rake 'posts:remap[find,replace,string,true]'

Example results:

find —> replace
Find —> replace
FIND —> replace
finders keepers —> replaceers keepers
finding —> replaceing

Regex replacement

For advanced replacements with regex, format the command accordingly:

rake 'posts:remap[(?<!\\w)(?=\\w)find(?<=\\w)(?!\\w),replace,regex]'

Example results:

replace —> replace
Find —> Find
FIND —> FIND
finders keepers —> finders keepers
finding —> finding

Deleting words or strings

To completely remove a word or string, apply these commands:

Basic case-sensitive deletion

rake 'posts:delete_word[word-to-delete]'

Case-insensitive deletion

rake 'posts:delete_word[word-to-delete,string,true]'

Regex deletion

rake 'posts:delete_word[\\[color=#[0-9a-fA-F]{3,6}\\],regex]'

Last edited by @SaraDev 2024-11-14T00:39:05Z

Check documentPerform check on document:
70 Curtiram
Batch processing to search and replace in all posts
Global Replace across database
[Announce] Search & replace / batch process Discourse posts
How do I change the legacy CDN URLs of images in posts?
How to automatically replace a double exclamation point when a message is saved?
Administrative Bulk Operations
Replacing content in multiple topics with Regex?
Is there a way to easily replace the word "Topic" everywhere on my site at once
Youtube embeds missing
Bulk replacement in translated strings?
Shouldn't users be able to delete their accounts whenever they want?
Updating image URL's after a domain change
Tool to remove email addresses from posts
Fix quotes after phpBB import
Remove BBCode and convert to Markdown
Forum Link Checker
Switch from TAGS to TAG broke links in posts and "Delete Unused Tags"
Search and Replace a text string in the post database
Watched words - replace link/url works in test but not in post
Permalink question (rewriting/redirecting old gallery contents)
Localised inline date/time
How to fix formatting issues? - markdown badly migrated to HTML
How to run rake posts:remap with domain?
Migrate a phpBB3 forum to Discourse
Discourse Doc Categories
What is rebaking and is it necessary when moving a server?
Discourse s3 backup folder
Pin more than one topic globally
After migrating from XenForo to Discourse
Update URLs inside a poll after changing CDN
How to handle changing organizational roles, re. past mentions on the forum
Hosted to self-hosted migration: past uploads still reference discourse infra
Trouble with `discourse remap` remapping `topic_links url`
CommonMark testing started here!
Remove images from PMs that have been inactive for >1 year
Masonry Image Gallery
Redirect Article- possible?
Upload links broken after S3 bucket change
How to search and replace URL instances throughout topics?
Enable a CDN for your Discourse
How do I move my s3 upload bucket from one provider to another?
Imgur images broken
Move from BackBlaze B2 to Digital Ocean Spaces
What's the fastest way to replace strings with multiple regexes in 1 million posts?
Too many user emails domains not working lead to mailgun domain disabled: what to do?
Renaming uploaded files
After rebuilding, avatar photos are missing
The change of from "tags" to "tag" in its URL affects my Discourse since they are linked in many posts. How can I automatically change them?

Como eu faria isso apenas para os tópicos em uma única categoria?

Meu caso de uso é um feed RSS importado que, irritantemente, exibe um ? em vez de um '. E como o feed é um feed de notícias com muitas citações, isso é um problema!

1 Curtiu

Você faria isso a partir do Rails, e será difícil porque as postagens não pertencem a categorias, os tópicos sim. Parece que você precisa de um plugin se este for um problema contínuo. Você poderia ser inteligente com um join ou apenas fazer um loop como

Topics.where(category_id: 123).each do |t|
  posts.where(topic_id: t, post_number: 1).each do |p|
    if p.raw.match("\?")
        p.raw.gsub!("\?","'")
        p.save
    end
  end
end

Se não for apenas em post_number: , não inclua isso.

Se não for um grande número de postagens, então isso provavelmente é bom o suficiente, se é que funciona.

1 Curtiu

Obrigado, Jay! Isso resolveria o problema perfeitamente.

Preciso mesmo solucionar isso corretamente e ver se há uma correção upstream. Ou talvez eu precise adicionar algo ao Plugin de Pesquisa RSS, que é uma fera um tanto complicada!

1 Curtiu

Apenas um palpite, mas você está vendo algum outro problema com posts criados a partir do feed RSS? Os caracteres ? estão presentes quando você visualiza a origem do feed? Estou me perguntando se o que você está encontrando é um problema de codificação.

2 Curtiram

Sim, estou vendo isso agora. Os ? estão lá sempre que há um caractere incomum, então é um problema na origem do RSS. Acontece que ' é apenas o mais comum, mas também está acontecendo com ā, \" e um ou dois outros.

Infelizmente, a empresa de software envolvida não é tão responsiva quanto a equipe do Discourse :kissing_heart:! Deseje-me sorte.

2 Curtiram

Era isso que eu também estava suspeitando. Pode ser tão simples quanto detectar melhor a codificação correta.

3 Curtiram

Alguma orientação para substituir como abaixo, por favor?

[member=12345] → @

Usei este exemplo que funciona para substituir um URL. No entanto, não está funcionando para frases.

Exemplo:

rake posts:remap["Eu Não Quero Esta Frase","Mas Eu Quero Esta Outra","string",true]

Continuo recebendo este erro:

ERROR: Expecting rake posts:remap['find','replace',type] where type is string or regex

Tentei com as aspas simples como mostrado na mensagem de erro, mas sem sucesso. Até tentei colocar hifens entre as palavras, como no exemplo de exclusão de palavras. Isso deu o mesmo erro.

Algum conselho?

Receio que, se você precisar fazer algo com aspas, é melhor fazê-lo no Rails. Com a tarefa do Rake, você tem que lidar tanto com bash quanto com o Rails para escapar. Você pode ser capaz de usar um monte de barras invertidas (que também precisam ser escapadas), mas provavelmente não.

Dê uma olhada no exemplo do Rails que tenho acima e veja se faz sentido. Tentarei adicionar algo ao OP na próxima vez que tiver um laptop.

1 Curtiu

Obrigado pela resposta. Isso parece estar acima do meu nível, mas com certeza posso aprender.

Parece que as aspas na string de texto foram o que causaram meu problema…

Meu propósito é que eu me vejo mudando títulos e URLs do meu blog, então gosto de voltar ao fórum e atualizar esses links, os títulos e as URLs também. Posso ver isso como uma tarefa semi-regular quando estou trabalhando em SEO. Quaisquer detalhes adicionais seriam fantásticos.

1 Curtiu

Deve haver algo que não estou entendendo aqui. Estou tentando substituir ocorrências de :THUMBS-UP: por :+1: em quase 3 milhões de posts (incluindo mensagens privadas). Eu executei:
rake posts:remap[":THUMBS-UP:",":+1:"]
E depois de cerca de 50 minutos de ................. ele retornou 40000 posts remapped! Este parece um número suspeitosamente redondo. Eu encontrei algumas ocorrências que foram substituídas por :+1: tanto em posts recentes quanto em posts de muitos anos atrás, mas também há um monte de :THUMBS-UP: mesmo nos mesmos tópicos que também têm algumas substituições bem-sucedidas de :+1:.

Isso parece um pouco estranho. Você tentou remapear novamente?
Você também pode retornar facilmente o número de posts que ainda contêm :THUMBS-UP: usando o data-explorer, se essa informação puder ser útil.

Sim, é estranho. Eu tentei executar o mesmo comando dois três vezes mais, e cada vez ele remapeou mais 333 posts… :question:

No log, ele está mostrando um monte de supostas substituições, exceto que quando eu recarrego a página e inspeciono o post real, ele permanece inalterado:

Isso me pareceu um problema de cache, então eu fiz um redis-cli flushall e recarreguei o Discourse forçadamente, mas ainda nenhuma mudança nos posts que foram relatados como editados no log.

E também no log de erros, um monte de mensagens como esta:
Screenshot from 2023-01-06 12-47-36

Isso deve funcionar… mas um dos problemas é que parece que você pode citar outras coisas, como vírgulas, mas não pode, já que as aspas são consumidas pelo shell, não pelo parser do rake.

por exemplo:

→ rake posts:remap["a,b","a+b"]
ERRO: Esperado rake posts:remap['encontrar','substituir',tipo] onde tipo é string ou regex

E os colchetes devem ser citados, pois são metacaracteres do shell. Você nem conseguirá executar o comando com um arquivo chamado posts:remapa no diretório (por mais improvável que isso seja) ou com failglob definido.

Eu acho que deveríamos mudar esses comandos - eles são enganosos no sentido de que parecem que você está citando as strings que estão sendo substituídas, mas na verdade não estamos. As aspas são consumidas pelo shell; o rails nunca as vê. Não há razão para ter as aspas, e se o rails as vir, elas farão parte da string:

→ rake 'posts:remap["find","replace"]'
Você tem certeza que deseja substituir todas as ocorrências de string de '"find"' por '"replace"'? (S/n)

Alguns exemplos adicionais, incluindo como lidar com coisas como vírgulas, são:

rake 'posts:remap[find,replace,string,true]'
rake $'posts:remap[string com uma aspa\\',string sem aspa]'
rake 'posts:remap[a\\, b,a+b]'

embora, curiosamente, isso funcione:

→ rake 'posts:remap[string com um colchete] seja citado\] ou não,string sem um colchete]'
Você tem certeza que deseja substituir todas as ocorrências de string de 'string com um colchete] seja citado] ou não' por 'string sem um colchete'? (S/n)
1 Curtiu

É possível que o texto bruto tenha sido alterado, mas a (nova) postagem ainda não foi processada?

Eu também pensei nisso, mas não, eu cliquei no botão de editar nessas postagens e o código bruto não foi alterado. E nas substituições bem-sucedidas, o novo emoji aparece sem um “rebake”.

1 Curtiu

Então, estou tentando substituir mais de 600 instâncias de links importados do YouTube, mas parece que só funciona quando está em uma linha própria.

Então, preciso inserir uma nova linha antes do próprio link do YouTube. Felizmente, tenho uma string do tipo “replaceme” que pode ser substituída pela nova linha.

A maneira apropriada de fazer uma nova linha em Ruby? Ou uma nova linha em Markdown?

Algo assim funcionaria?

rake posts:remap["replaceme","\n",string,true]

Ou preciso escapar o \n algumas vezes?

rake posts:remap["replaceme","\\\n",string,true]

Ou devo mirar na nova linha do markdown (que é uma única barra invertida, correto?):

rake posts:remap["replaceme","\",string,true]

Acho que também teria que escapar isso?

Qualquer orientação é apreciada.

Eu faria isso no Rails, onde você não precisa se preocupar com tantos níveis de citação.

2 Curtiram

Boa ideia. Escapar coisas faz minha cabeça doer.

Vejo que seu código acima é simples o suficiente. Algo como isto?

Topics.where(category_id: 123).each do |t|
  posts.where(topic_id: t).each do |p|
    p.raw.gsub("replaceme","/")
  end
end

Algo assim? Presumo que a barra de markdown / seja melhor do que usar CR/LF ou \n, ou mesmo \u003cbr /\u003e ou o que quer que seja?

Como se executa isso do shell? Basta digitar “rails” e depois colar o código lá?