Remplacer une chaîne de caractères dans tous les messages

: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 « J'aime »

Comment ferais-je cela pour uniquement les sujets d’une seule catégorie ?

Mon cas d’utilisation est un flux RSS importé qui affiche de manière agaçante un ? au lieu d’une apostrophe ('). Comme le flux est un fil d’actualités avec beaucoup de citations, cela pose problème !

1 « J'aime »

Vous le feriez depuis Rails, et ce sera difficile car les publications n’appartiennent pas aux catégories, mais les sujets oui. Cela ressemble à ce dont vous avez besoin d’un plugin si c’est un problème continuel. Vous pourriez être astucieux avec une jointure ou simplement boucler comme

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

Si ce n’est pas seulement dans post_number: , n’incluez pas cela.

Si ce n’est pas un grand nombre de publications, alors c’est probablement suffisant, si cela fonctionne d’ailleurs.

1 « J'aime »

Merci Jay ! Cela ferait très bien l’affaire.

Je dois le dépanner correctement et voir s’il existe une solution en amont. Ou je devrai peut-être ajouter quelque chose au Plugin de sondage RSS, qui est une bête un peu délicate !

1 « J'aime »

Juste une supposition, mais rencontrez-vous d’autres problèmes avec les messages créés à partir du flux RSS ? Les caractères ? sont-ils présents lorsque vous affichez la source du flux ? Je me demande si ce que vous rencontrez est un problème d’encodage.

2 « J'aime »

Oui, je regarde ça maintenant. Les ? sont là chaque fois qu’il y a un caractère inhabituel, donc c’est un problème du côté de la source RSS. Il s’avère que ' est juste le plus courant, mais cela se produit aussi pour ā, \", et un ou deux autres.

Malheureusement, la société éditrice du logiciel n’est pas aussi réactive que l’équipe Discourse :kissing_heart: ! Souhaitez-moi bonne chance.

2 « J'aime »

C’est ce que je suspectais aussi. Il pourrait être aussi simple que de mieux détecter le bon encodage.

3 « J'aime »

Une aide pour remplacer comme ci-dessous s’il vous plaît ?

[member=12345] → @

J’ai utilisé cet exemple qui fonctionne pour remplacer une URL. Cependant, il ne fonctionne pas pour les phrases.

Exemple :

rake posts:remap["Je ne veux pas de cette phrase","Mais je veux celle-ci","chaîne",true]

J’obtiens cette erreur :

ERREUR : Attendu rake posts:remap['trouver','remplacer',type] où type est chaîne ou regex

J’ai essayé avec les guillemets simples comme indiqué dans le message d’erreur, mais sans succès. J’ai même essayé en plaçant des tirets entre les mots comme dans l’exemple de suppression de mot. Cela a donné la même erreur.

Des conseils ?

Je crains que si vous devez faire quelque chose avec des guillemets, il est préférable de le faire dans Rails. Avec la tâche rake, vous devez gérer à la fois bash et Rails pour l’échappement. Vous pourriez être en mesure d’utiliser un tas d’antislashs (qui doivent également être échappés), mais probablement pas.

Regardez l’exemple Rails que j’ai ci-dessus et voyez s’il est logique. J’essaierai d’ajouter quelque chose à l’OP la prochaine fois que j’aurai un ordinateur portable.

1 « J'aime »

Merci pour votre réponse. Cela dépasse mes compétences, mais je peux certainement apprendre.

Il semble que les guillemets dans la chaîne de caractères soient la cause de mon problème…

Mon objectif est de modifier les titres et les URL de mon blog, donc j’aime revenir sur le forum pour mettre à jour ces liens, ainsi que les titres et les URL. Je vois que cela pourrait être une tâche semi-régulière lorsque je travaille sur le référencement. Tout détail supplémentaire serait fantastique.

1 « J'aime »

Il doit y avoir quelque chose que je ne comprends pas ici. J’essaie de remplacer les occurrences de :THUMBS-UP: par :+1: dans près de 3 millions de messages (y compris les messages privés). J’ai exécuté :
rake posts:remap[\":THUMBS-UP:\",\":+1:\"]
Et après environ 50 minutes de ................., il a retourné 40000 posts remapped! Cela semble être un nombre suspectement rond. J’ai trouvé certaines occurrences qui ont été remplacées par :+1: dans des messages récents et des messages d’il y a plusieurs années, mais il y a aussi une tonne de :THUMBS-UP: même dans les mêmes fils de discussion qui ont également des remplacements réussis de :+1:.

Cela semble un peu étrange. Avez-vous essayé de remapper à nouveau ?
Vous pouvez également renvoyer facilement le nombre de publications qui contiennent encore :THUMBS-UP: en utilisant data-explorer si cette information peut vous être utile.

Oui, c’est bizarre. J’ai essayé d’exécuter la même commande deux trois fois de plus, et à chaque fois, cela a remappé 333 publications supplémentaires… :question:

Dans le journal, il y a un tas de remplacements supposés, sauf que lorsque je recharge la page et que j’inspecte la publication réelle, elle reste inchangée :

Cela m’a semblé être un problème de mise en cache, j’ai donc effectué un redis-cli flushall et rechargé Discourse en dur, mais toujours aucun changement dans les publications signalées comme modifiées dans le journal.

Et aussi dans le journal d’erreurs, un tas de messages comme celui-ci :
Screenshot from 2023-01-06 12-47-36

Cela devrait aller… mais l’un des problèmes est que cela ressemble à la possibilité de citer d’autres choses comme des virgules, mais ce n’est pas le cas car les guillemets sont consommés par le shell, et non par l’analyseur rake.

par exemple :

→ rake posts:remap["a,b","a+b"]
ERROR: Expecting rake posts:remap['find','replace',type] where type is string or regex

Et les crochets doivent être cités car ce sont des métacaractères du shell eux-mêmes. Vous ne pourrez même pas exécuter la commande avec un fichier nommé posts:remapa dans le répertoire (aussi improbable que cela puisse être) ou avec failglob défini.

Je pense que nous devrions changer ces commandes - elles sont trompeuses dans le sens où elles ressemblent à la citation des chaînes remplacées, mais ce n’est pas vraiment le cas. Les guillemets sont consommés par le shell ; rails ne les voit jamais. Il n’y a aucune raison d’avoir les guillemets, et si rails les voit, ils feront partie de la chaîne :

→ rake 'posts:remap["find","replace"]'
Êtes-vous sûr de vouloir remplacer toutes les occurrences de chaîne de '\"find\"' par '\"replace\"' ? (O/n)

Quelques exemples supplémentaires, y compris comment gérer les choses comme les virgules, sont :

rake 'posts:remap[find,replace,string,true]'
rake $'posts:remap[string with a quote\\',string without a quote]'
rake 'posts:remap[a\\, b,a+b]'

bien que, curieusement, cela fonctionne :

→ rake 'posts:remap[string with a bracket] either quoted\] or not,string without a bracket]'
Êtes-vous sûr de vouloir remplacer toutes les occurrences de chaîne de 'string with a bracket] either quoted] or not' par 'string without a bracket' ? (O/n)
1 « J'aime »

Est-il possible que le brut soit modifié, mais que le (nouveau) message ne soit pas encore traité ?

J’y ai pensé aussi, mais non, j’ai cliqué sur le bouton modifier de ces publications et le brut n’a pas changé. Et sur les remplacements réussis, le nouvel emoji apparaît sans re-cuisson.

1 « J'aime »

J’essaie de remplacer plus de 600 instances de liens YouTube importés, mais cela ne semble fonctionner que lorsqu’ils sont seuls sur une ligne.

Je dois donc insérer un saut de ligne avant le lien YouTube lui-même. Heureusement, j’ai une chaîne de type « replaceme » qui peut être remplacée par le saut de ligne.

Est-ce la bonne façon de faire un saut de ligne Ruby ? Ou un saut de ligne Markdown ?

Est-ce que quelque chose comme ceci fonctionnerait ?

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

Ou dois-je échapper le \n plusieurs fois ?

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

Ou devrais-je opter pour le saut de ligne Markdown (qui est une seule barre oblique inverse, n’est-ce pas) :

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

Je suppose que je devrais aussi l’échapper ?

Toute aide est appréciée.

Je le ferais dans Rails où vous n’avez pas à vous soucier d’autant de niveaux de citation.

2 « J'aime »

Bonne idée. Les échappements me donnent mal à la tête.

Je vois que votre code ci-dessus est assez simple. Quelque chose comme ça ?

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

Quelque chose comme ça ? Je suppose que le markdown / est préférable à l’utilisation de CR/LF ou \n, ou même \u003cbr /\u003e ou autre chose ?

Comment exécute-t-on cela depuis le shell ? Il suffit de taper “rails” puis de copier le code à l’intérieur ?