在所有帖子中替换字符串

: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 个赞

如何只针对单个类别中的主题执行此操作?

我的用例是导入的 RSS 提要,它烦人地显示 ? 而不是 '。由于该提要是新闻提要,其中包含大量引语,因此这是一个问题!

1 个赞

您需要从 Rails 进行操作,这会比较困难,因为帖子不属于分类,而主题属于。如果这是一个持续存在的问题,听起来您需要一个插件。您可以巧妙地使用联接,或者像这样循环:

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

如果不是仅在 post_number: 中,则不包含该部分。

如果帖子数量不是很大,那么这可能就足够了,如果它能正常工作的话。

1 个赞

谢谢 Jay!这会很好地解决问题。

我确实需要正确地对其进行故障排除,看看是否有上游修复。或者我可能需要对 RSS Polling Plugin 进行一些补充,这有点棘手!

1 个赞

只是猜测一下,您是否还遇到来自 RSS 源的帖子的其他问题?在查看源的提要时,是否会出现 ? 字符?我想知道您遇到的问题是否是编码问题。

2 个赞

是的,我现在就看这个。每次出现不寻常的字符时,里面都有 ?,所以这是 RSS 源端的问题。事实证明,' 只是最常见的字符,但 ā\" 和其他一两个字符也出现了这种情况。

不幸的是,所涉及的软件公司不像 Discourse 团队那样响应迅速 :kissing_heart:!祝我好运。

2 个赞

我也是这么想的。也许只需更好地检测正确的编码即可。

3 个赞

请问如何将其替换为如下内容?

[member=12345] → @

我使用了这个示例,它可以替换 URL。但是,它不适用于短语。

示例:

rake posts:remap["I Don't Want This Phrase","But I Do Want This One","string",true]

我一直收到这个错误:

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

我也尝试了错误消息中显示的单引号,但没有成功。我甚至尝试像删除单词示例那样在单词之间放置连字符。结果是相同的错误。

有什么建议吗?

我担心如果你需要处理引号,最好在 rails 中进行。使用 rake 任务,你必须同时处理 bash 和 rails 来转义。你可能需要使用一堆反斜杠(也需要转义),但可能不行。

看看我上面提供的 rails 示例,看看是否有意义。下次我拿到笔记本电脑时,我会往 OP 中添加一些内容。

1 个赞

感谢您的回复。这超出了我的能力范围,但我可以学习。

听起来文本字符串中的引号是导致我问题的原因……

我的目的是更改博客的标题和网址,因此我喜欢回到论坛更新这些链接、标题和网址。我认为在进行 SEO 工作时,这项任务会变得相当频繁。如果能提供更多细节,那就太好了。

1 个赞

我一定有什么地方没弄明白。我正试图将近 300 万条帖子(包括私信)中的 :THUMBS-UP: 替换为 :+1:。我运行了:
rake posts:remap[\":THUMBS-UP:\",\":+1:\"]
大约 50 分钟后,它返回了 40000 posts remapped! 这个数字看起来可疑地规整。我确实发现了一些在最近的帖子和很多年前的帖子中被替换成了 :+1: 的情况,但在那些也有成功替换成 :+1: 的帖子中,仍然有大量的 :THUMBS-UP: 存在。

这似乎有点奇怪。你再试着重新映射了吗?
如果你想用数据资源管理器(data-explorer)来统计仍然包含 :THUMBS-UP: 的帖子数量,也可以轻松做到,如果这些信息对你有用的话。

是的,这很奇怪。我尝试了另外三次运行相同的命令 two three,每次都重新映射了另外 333 个帖子…… :question:

日志显示了一堆所谓的替换,但当我重新加载页面并检查实际帖子时,它仍然没有改变:

这看起来像是一个缓存问题,所以我运行了 redis-cli flushall 并硬刷新了 Discourse,但日志中报告已编辑的帖子仍然没有变化。

并且错误日志中也出现了一堆类似这样的消息:
Screenshot from 2023-01-06 12-47-36

这应该没问题……但其中一个问题是,它看起来你可以引用其他东西,比如逗号,但你不能,因为引号被 shell 消耗掉了,而不是被 rake 解析器消耗掉。

例如:

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

并且括号应该被引用,因为它们本身就是 shell 元字符。你甚至无法在目录中运行一个名为 posts:remapa 的命令(尽管这不太可能)或在设置了 failglob 的情况下运行。

我认为我们应该更改这些命令——它们具有误导性,因为它们看起来你正在引用被替换的字符串,但实际上我们并没有。引号被 shell 消耗掉了;rails 从未见过它们。没有理由甚至要加引号,如果 rails 确实看到了它们,它们将成为字符串的一部分:

→ rake 'posts:remap["find","replace"]'
Are you sure you want to replace all string occurrences of '"find"' with '"replace"'? (Y/n)

更多示例,包括如何处理逗号等内容是:

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]'

尽管如此,奇怪的是,这有效:

→ rake 'posts:remap[string with a bracket] either quoted\] or not,string without a bracket]'
Are you sure you want to replace all string occurrences of 'string with a bracket] either quoted] or not' with 'string without a bracket'? (Y/n)
1 个赞

原始帖子是否已更改,但(新)帖子尚未生成?

我也这么想过,但没有,我点击了那些帖子的编辑按钮,原始内容没有改变。在成功的替换中,新的表情符号会显示出来,而无需重新烘焙。

1 个赞

我正在尝试替换 600 多个导入的 YouTube 链接的实例,但似乎只有当它单独占一行时才有效。

所以我需要在 YouTube 链接本身之前插入一个换行符。幸运的是,我有一个可以替换为换行符的“replaceme”类型的字符串。

这是 Ruby 换行符的正确方法吗?还是 Markdown 换行符?

像这样可以吗?

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

还是我需要多次转义 \n

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

或者我应该使用 Markdown 换行符(那是单个反斜杠,对吗?):

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

我猜我也需要转义那个?

任何指导都将不胜感激。

我会在 Rails 中这样做,这样您就不必担心如此多的引用级别。

2 个赞

好主意。转义字符让我头疼。

我看到你上面的代码很容易理解。是不是像这样?

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

大概是这样吗?我猜 markdown / 比使用 CR/LF 或 \n,甚至 \u003cbr /\u003e 或其他什么更好?

如何在 shell 中运行它?直接输入“rails”然后把代码复制进去吗?