Reemplazar una cadena en todas las publicaciones

: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 Me gusta

¿Cómo haría esto solo para los temas de una sola categoría?

Mi caso de uso es un feed RSS importado que, molesta, muestra un ? en lugar de un '. Y como el feed es un feed de noticias con muchas citas, ¡esto es un problema!

1 me gusta

Lo harías desde Rails, y será difícil porque las publicaciones no pertenecen a las categorías, los temas sí. Parece que necesitas un plugin si este es un problema continuo. Podrías ser ingenioso con una unión o simplemente iterar 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

Si no está solo en post_number: , no lo incluyas.

Si no es un gran número de publicaciones, entonces esto probablemente sea suficiente, si es que funciona.

1 me gusta

¡Gracias Jay! Eso sería de gran ayuda.

Necesito solucionarlo adecuadamente y ver si hay una solución upstream. O podría necesitar añadir algo al Plugin de sondeo RSS, ¡que es una bestia un tanto complicada!

1 me gusta

Solo una suposición, pero ¿estás viendo algún otro problema con las publicaciones creadas a partir del feed RSS? ¿Están presentes los caracteres ? cuando ves el código fuente del feed? Me pregunto si lo que estás experimentando es un problema de codificación.

2 Me gusta

Sí, lo estoy revisando ahora mismo. Los ? aparecen cada vez que hay un carácter inusual, así que es un problema en el extremo de origen del RSS. Resulta que ' es solo el más común, pero también está sucediendo con ā, \" y uno o dos más.

Desafortunadamente, la empresa de software involucrada no es tan receptiva como el equipo de Discourse :kissing_heart:! Deséame suerte.

2 Me gusta

Eso es lo que sospechaba también. Podría ser tan simple como detectar mejor la codificación correcta.

3 Me gusta

¿Alguna guía para reemplazar como a continuación, por favor?

[member=12345] → @

Usé este ejemplo que funciona para reemplazar una URL. Sin embargo, no funciona para frases.

Ejemplo:

rake posts:remap["No Quiero Esta Frase","Pero Sí Quiero Esta Otra","string",true]

Sigo recibiendo este error:

ERROR: Se espera rake posts:remap['find','replace',type] donde type es string o regex

Lo intenté con las comillas simples como se muestra en el mensaje de error, pero tampoco funcionó. Incluso intenté colocar guiones entre las palabras como en el ejemplo de eliminar palabras. Eso me dio el mismo error.

¿Algún consejo?

Me temo que si necesitas hacer algo con comillas, lo mejor es hacerlo en Rails. Con la tarea de Rake, tienes que lidiar tanto con bash como con Rails para escapar. Es posible que puedas usar un montón de barras invertidas (que también necesitan ser escapadas), pero probablemente no.

Echa un vistazo al ejemplo de Rails que tengo arriba y ve si tiene sentido. Intentaré añadir algo al OP la próxima vez que tenga un portátil.

1 me gusta

Gracias por la respuesta. Eso parece estar por encima de mis posibilidades, pero seguro que puedo aprender.

Parece que las comillas en la cadena de texto fueron las que causaron mi problema…

Mi propósito, me encuentro cambiando títulos y URLs de mi blog, así que me gusta volver al foro y actualizar esos enlaces, los títulos y las URLs también. Puedo ver que esta será una tarea semirregular cuando esté trabajando en SEO. Cualquier detalle adicional sería fantástico.

1 me gusta

Debe haber algo que no entiendo aquí. Estoy intentando reemplazar ocurrencias de :THUMBS-UP: con :+1: en casi 3 millones de publicaciones (incluidos los mensajes privados). Ejecuté:
rake posts:remap[":THUMBS-UP:",":+1:"]
Y después de unos 50 minutos de ................. devolvió ¡40000 publicaciones reasignadas! Este parece un número sospechosamente exacto. Encontré algunas ocurrencias que fueron reemplazadas por :+1: tanto en publicaciones recientes como en publicaciones de hace muchos años, pero también hay una tonelada de :THUMBS-UP: incluso en los mismos hilos de temas que también tienen algunos reemplazos exitosos de :+1:.

Eso parece un poco extraño. ¿Intentaste reasignar de nuevo?
También puedes devolver fácilmente el número de publicaciones que todavía contienen :THUMBS-UP: usando el explorador de datos si esta información puede ser de alguna utilidad.

Sí, es extraño. Intenté ejecutar el mismo comando dos tres veces más, y cada vez reasignó 333 publicaciones más… :question:

En el registro, se muestran un montón de supuestos reemplazos, excepto que cuando recargo la página e inspecciono la publicación real, permanece sin cambios:

Esto me pareció un problema de caché, así que ejecuté un redis-cli flushall y recargué forzosamente Discourse, pero todavía no hay cambios en las publicaciones que se informaron como editadas en el registro.

Y también en el registro de errores, un montón de mensajes como este:
Screenshot from 2023-01-06 12-47-36

Esto debería estar bien… pero uno de los problemas es que parece que puedes citar otras cosas como comas, pero no puedes, ya que las comillas son consumidas por el shell, no por el analizador de rake.

por ejemplo:

→ rake posts:remap["a,b","a+b"]
ERROR: Se espera rake posts:remap['buscar','reemplazar',tipo] donde tipo es string o regex

Y los corchetes deben ser citados ya que son metacaracteres del shell. Ni siquiera podrás ejecutar el comando con un archivo llamado posts:remapa en el directorio (por improbable que sea) o con failglob establecido.

Creo que deberíamos cambiar estos comandos: son engañosos en el sentido de que parece que estás citando las cadenas que se reemplazan, pero en realidad no lo estamos haciendo. Las comillas son consumidas por el shell; rails nunca las ve. No hay razón para tener las comillas, y si rails las ve, serán parte de la cadena:

→ rake 'posts:remap["find","replace"]'
¿Está seguro de que desea reemplazar todas las ocurrencias de cadena de '\"find\"' con '\"replace\"'? (S/n)

Algunos ejemplos más, incluyendo cómo tratar cosas como comas, son:

rake 'posts:remap[find,replace,string,true]'
rake $'posts:remap[cadena con una comilla\\',cadena sin comilla]'
rake 'posts:remap[a\\, b,a+b]'

aunque, curiosamente, esto funciona:

→ rake 'posts:remap[cadena con un corchete] ya sea entre comillas\\] o no,cadena sin corchete]'
¿Está seguro de que desea reemplazar todas las ocurrencias de cadena de 'cadena con un corchete] ya sea entre comillas] o no' con 'cadena sin corchete'? (S/n)
1 me gusta

¿Es posible que el texto sin procesar se cambie, pero la publicación (nueva) aún no se haya procesado?

Yo también pensé en eso, pero no, hice clic en el botón de editar en esas publicaciones y el código fuente no ha cambiado. Y en los reemplazos exitosos, el nuevo emoji aparece sin volver a hornear.

1 me gusta

Así que estoy intentando reemplazar más de 600 instancias de enlaces de YouTube importados, pero parece que solo funciona cuando está solo en una línea.

Así que necesito insertar una nueva línea antes del propio enlace de YouTube. Afortunadamente, tengo una cadena de tipo “replaceme” que se puede reemplazar con la nueva línea.

¿Es la forma apropiada de hacer una nueva línea en Ruby? ¿O una nueva línea en Markdown?

¿Funcionaría algo como esto?

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

¿O necesito escapar el \n unas cuantas veces?

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

¿O debería apuntar a la nueva línea de Markdown (que es una sola barra invertida, ¿correcto?):

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

Supongo que también tendría que escapar eso?

Agradezco cualquier orientación.

Lo haría en Rails, donde no tienes que preocuparte por tantos niveles de comillas.

2 Me gusta

Buena idea. Escapar cosas me duele la cabeza.

Veo que tu código anterior es bastante fácil. ¿Algo como esto?

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

¿Algo así? Supongo que el markdown / es mejor que usar CR/LF o \n, o incluso \u003cbr /\u003e o lo que sea?

¿Cómo se ejecuta esto desde la shell? ¿Simplemente escribes “rails” y luego copias el código allí?