Replace a string in all posts

: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 Mi Piace

Come potrei farlo solo per gli argomenti di una singola categoria?

Il mio caso d’uso è un feed RSS importato che visualizza fastidiosamente un ? invece di un '. E poiché il feed è un feed di notizie con molte citazioni, questo è un problema!

1 Mi Piace

Lo faresti da rails, e sarà difficile perchÊ i post non appartengono alle categorie, ma gli argomenti sÏ. Sembra che tu abbia bisogno di un plugin se questo è un problema continuo. Potresti essere intelligente con un join o semplicemente ciclare come

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 non è solo in post_number: , non includerlo.

Se non si tratta di un numero enorme di post, allora questo è probabilmente abbastanza buono, se funziona almeno.

1 Mi Piace

Grazie Jay! Farebbe al caso mio.

Devo risolvere il problema correttamente e vedere se c’è una soluzione upstream. Oppure potrei dover aggiungere qualcosa al plugin di polling RSS che è una bestia un po’ complicata!

1 Mi Piace

Solo un’ipotesi, ma stai riscontrando altri problemi con i post creati dal feed RSS? I caratteri ? sono presenti quando visualizzi il sorgente del feed? Mi chiedo se quello che stai riscontrando sia un problema di codifica.

2 Mi Piace

Sì, ci sto dando un’occhiata ora. I ? ci sono ogni volta che c’è un carattere insolito, quindi è un problema lato sorgente RSS. Si scopre che ' è semplicemente il più comune, ma sta succedendo anche per ā, \" e uno o due altri.

Sfortunatamente, l’azienda software coinvolta non è reattiva come il team di Discourse :kissing_heart:! Auguratemi buona fortuna.

2 Mi Piace

Era anche quello che sospettavo. Potrebbe essere semplice come rilevare meglio la codifica corretta.

3 Mi Piace

Qualche indicazione per sostituire come segue per favore?

[member=12345] → @

Ho usato questo esempio che funziona per la sostituzione di un URL. Tuttavia, non funziona per le frasi.

Esempio:

rake posts:remap["Non Voglio Questa Frase","Ma Voglio Questa","string",true]

Continuo a ricevere questo errore:

ERRORE: Atteso rake posts:remap['trova','sostituisci',tipo] dove tipo è string o regex

Ho provato con le virgolette singole come mostrato nel messaggio di errore, ma senza successo. Ho anche provato a inserire trattini tra le parole come nell’esempio di eliminazione di parole. Ha dato lo stesso errore.

Qualche consiglio?

Temo che se devi fare qualcosa con le virgolette, è meglio farlo in Rails. Con il rake task, devi gestire sia bash che Rails per l’escape. Potresti essere in grado di usare un sacco di backslash (che devono anche essere escapati), ma probabilmente no.

Dai un’occhiata all’esempio di Rails che ho sopra e vedi se ha senso. Aggiungerò qualcosa all’OP la prossima volta che avrò un laptop.

1 Mi Piace

Grazie per la risposta. Sembra che vada oltre le mie capacitĂ , ma posso sicuramente imparare.

Sembra che le virgolette nella stringa di testo siano ciò che ha causato il mio problema…

Il mio scopo, mi ritrovo a cambiare titoli e URL del mio blog, quindi mi piace tornare al forum e aggiornare quei link, i titoli e gli URL. Posso vedere che questo sarà un compito semi-regolare quando lavorerò sulla SEO. Qualsiasi ulteriore dettaglio sarebbe fantastico.

1 Mi Piace

C’è qualcosa che non sto capendo qui. Sto cercando di sostituire le occorrenze di :THUMBS-UP: con :+1: in quasi 3 milioni di post (inclusi i PM). Ho eseguito:
rake posts:remap[":THUMBS-UP:",":+1:"]
E dopo circa 50 minuti di ................. ha restituito 40000 posts remapped! Questo sembra un numero sospettosamente pari. Ho trovato alcune occorrenze che sono state sostituite con :+1: sia nei post recenti che in quelli di molti anni fa, ma ci sono anche un sacco di :THUMBS-UP: anche negli stessi thread che hanno anche alcune sostituzioni riuscite di :+1:.

Sembra un po’ strano. Hai provato a rimappare di nuovo?
Puoi anche restituire facilmente il numero di post che contengono ancora :THUMBS-UP: utilizzando data-explorer, se queste informazioni possono essere utili.

Sì, è strano. Ho provato a eseguire lo stesso comando due altre tre volte, e ogni volta ha rimappato altri 333 post… :question:

Nel log vengono mostrate un sacco di presunte sostituzioni, tranne che quando ricarico la pagina e ispeziono il post effettivo, esso rimane invariato:

Questo mi è sembrato un problema di cache, quindi ho eseguito un redis-cli flushall e ho ricaricato a fondo Discourse, ma ancora nessun cambiamento nei post che sono stati segnalati come modificati nel log.

E anche nel log degli errori un sacco di messaggi come questo:
Screenshot from 2023-01-06 12-47-36

Questo dovrebbe andare bene… ma uno dei problemi è che sembra che tu possa citare altre cose come le virgole, ma non puoi poiché le virgolette vengono consumate dalla shell, non dal parser rake.

ad esempio:

→ rake posts:remap["a,b","a+b"]
ERRORE: Si aspettava rake posts:remap['trova','sostituisci',tipo] dove tipo è stringa o regex

E le parentesi dovrebbero essere citate poichĂŠ sono esse stesse metacaratteri della shell. Non sarai nemmeno in grado di eseguire il comando con un file chiamato posts:remapa nella directory (per quanto improbabile possa essere) o con failglob impostato.

Penso che dovremmo cambiare questi comandi - sono fuorvianti nel senso che sembrano che tu stia citando le stringhe che vengono sostituite, ma in realtà non lo stiamo facendo. Le virgolette vengono consumate dalla shell; rails non le vede mai. Non c’è motivo di avere nemmeno le virgolette, e se rails le vede faranno parte della stringa:

→ rake 'posts:remap["trova","sostituisci"]'
Sei sicuro di voler sostituire tutte le occorrenze della stringa '\"trova\"' con '\"sostituisci\"'? (S/n)

Altri esempi, inclusi come gestire cose come le virgole, sono:

rake 'posts:remap[trova,sostituisci,stringa,vero]'
rake $'posts:remap[stringa con una virgoletta\\',stringa senza virgoletta]'
rake 'posts:remap[a\\, b,a+b]'

anche se, stranamente, questo funziona:

→ rake 'posts:remap[stringa con una parentesi] quotata o meno\\] o non quotata,stringa senza parentesi]'
Sei sicuro di voler sostituire tutte le occorrenze della stringa 'stringa con una parentesi] quotata o meno] o non quotata' con 'stringa senza parentesi'? (S/n)
1 Mi Piace

È possibile che il “raw” sia cambiato, ma il (nuovo) post non sia ancora stato “baked”?

Ci ho pensato anch’io, ma no, ho premuto il pulsante di modifica su quei post e il codice sorgente non è cambiato. E sulle sostituzioni riuscite la nuova emoji appare senza una rielaborazione.

1 Mi Piace

Sto cercando di sostituire oltre 600 istanze di link YouTube importati, ma sembra funzionare solo quando sono da soli su una riga.

Quindi devo inserire un’interruzione di riga prima del link di YouTube stesso. Fortunatamente, ho una stringa di tipo “replaceme” che può essere sostituita con l’interruzione di riga.

È il modo appropriato per fare un’interruzione di riga Ruby? O un’interruzione di riga Markdown?

Funzionerebbe qualcosa del genere?

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

O devo sfuggire la \n alcune volte?

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

O dovrei puntare all’interruzione di riga Markdown (che è una singola barra rovesciata, corretto?):

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

Suppongo che dovrei sfuggire anche a quella?

Qualsiasi guida è apprezzata.

Lo farei in rails dove non devi preoccuparti di cosĂŹ tanti livelli di quoting.

2 Mi Piace

Buona idea. Scappare le cose mi fa venire il mal di testa.

Vedo che il tuo codice sopra è abbastanza facile. Qualcosa del genere?

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

Qualcosa del genere? Presumo che il markdown / sia migliore dell’uso di CR/LF o \n, o anche \u003cbr /\u003e o qualsiasi altra cosa?

Come si esegue questo dalla shell? Basta digitare “rails” e poi copiare il codice lì dentro?