mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-17 15:10:12 +01:00
🐛 查找替换中使用正则表达式后替换不正确 https://github.com/siyuan-note/siyuan/issues/6722
This commit is contained in:
parent
c20e936303
commit
bc17efcaad
7 changed files with 93 additions and 32 deletions
|
|
@ -960,7 +960,7 @@
|
||||||
"129": "Cloud data has been corrupted, please refer to <a href=\"https://ld246.com/article/1658499492287\" target=\"_blank\">here</a> to resolve the issue",
|
"129": "Cloud data has been corrupted, please refer to <a href=\"https://ld246.com/article/1658499492287\" target=\"_blank\">here</a> to resolve the issue",
|
||||||
"130": "Starting new version installer...",
|
"130": "Starting new version installer...",
|
||||||
"131": "This operation is not supported, please go to the cloud storage provider management console to operate",
|
"131": "This operation is not supported, please go to the cloud storage provider management console to operate",
|
||||||
"132": "TODO",
|
"132": "The current search method does not support the replace operation, please use the [Text] or [Regex] search method",
|
||||||
"133": "TODO",
|
"133": "TODO",
|
||||||
"134": "In order to prevent the newly restored data from being overwritten by synchronization, the data synchronization function has been automatically suspended",
|
"134": "In order to prevent the newly restored data from being overwritten by synchronization, the data synchronization function has been automatically suspended",
|
||||||
"135": "Unable to decrypt data. Make sure to use the same key on multiple devices, then create a new cloud directory to sync",
|
"135": "Unable to decrypt data. Make sure to use the same key on multiple devices, then create a new cloud directory to sync",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"searchMethod": "método de búsqueda",
|
"searchMethod": "método de búsqueda",
|
||||||
"regex": "regex",
|
"regex": "Regex",
|
||||||
"groupBy": "Agrupar por",
|
"groupBy": "Agrupar por",
|
||||||
"keywordsLimit": "Límite de palabras clave",
|
"keywordsLimit": "Límite de palabras clave",
|
||||||
"exportAsImage": "Exportar como imagen",
|
"exportAsImage": "Exportar como imagen",
|
||||||
|
|
@ -960,7 +960,7 @@
|
||||||
"129": "Los datos de la nube se han dañado, consulte <a href=\"https://ld246.com/article/1658499492287\" target=\"_blank\">aquí</a> para resolver el problema",
|
"129": "Los datos de la nube se han dañado, consulte <a href=\"https://ld246.com/article/1658499492287\" target=\"_blank\">aquí</a> para resolver el problema",
|
||||||
"130": "Iniciando instalador de nueva versión...",
|
"130": "Iniciando instalador de nueva versión...",
|
||||||
"131": "Esta solicitud no es compatible, vaya a la consola de administración del proveedor de almacenamiento en la nube para operar",
|
"131": "Esta solicitud no es compatible, vaya a la consola de administración del proveedor de almacenamiento en la nube para operar",
|
||||||
"132": "TODO",
|
"132": "El método de búsqueda actual no admite la operación de reemplazo, utilice el método de búsqueda [Texto] o [Regex]",
|
||||||
"133": "TODO",
|
"133": "TODO",
|
||||||
"134": "Para evitar que los datos recién restaurados sean sobrescritos por la sincronización, se ha suspendido automáticamente la función de sincronización de datos",
|
"134": "Para evitar que los datos recién restaurados sean sobrescritos por la sincronización, se ha suspendido automáticamente la función de sincronización de datos",
|
||||||
"135": "No se pueden descifrar los datos. Asegúrese de usar la misma clave en varios dispositivos, luego cree un nuevo directorio en la nube para sincronizar",
|
"135": "No se pueden descifrar los datos. Asegúrese de usar la misma clave en varios dispositivos, luego cree un nuevo directorio en la nube para sincronizar",
|
||||||
|
|
|
||||||
|
|
@ -960,7 +960,7 @@
|
||||||
"129": "Les données cloud ont été corrompues, veuillez vous référer à <a href=\"https://ld246.com/article/1658499492287\" target=\"_blank\">ici</a> pour résoudre le problème",
|
"129": "Les données cloud ont été corrompues, veuillez vous référer à <a href=\"https://ld246.com/article/1658499492287\" target=\"_blank\">ici</a> pour résoudre le problème",
|
||||||
"130": "Démarrage du programme d'installation de la nouvelle version...",
|
"130": "Démarrage du programme d'installation de la nouvelle version...",
|
||||||
"131": "Cette opération n'est pas prise en charge, veuillez vous rendre sur la console de gestion du fournisseur de stockage cloud pour opérer",
|
"131": "Cette opération n'est pas prise en charge, veuillez vous rendre sur la console de gestion du fournisseur de stockage cloud pour opérer",
|
||||||
"132": "TODO",
|
"132": "La méthode de recherche actuelle ne prend pas en charge l'opération de remplacement, veuillez utiliser la méthode de recherche [Texte] ou [Regex]",
|
||||||
"133": "TODO",
|
"133": "TODO",
|
||||||
"134": "Afin d'éviter que les données nouvellement restaurées ne soient écrasées par la synchronisation, la fonction de synchronisation des données a été automatiquement suspendue",
|
"134": "Afin d'éviter que les données nouvellement restaurées ne soient écrasées par la synchronisation, la fonction de synchronisation des données a été automatiquement suspendue",
|
||||||
"135": "Impossible de déchiffrer les données. Assurez-vous d'utiliser la même clé sur plusieurs appareils, puis créez un nouveau répertoire cloud à synchroniser",
|
"135": "Impossible de déchiffrer les données. Assurez-vous d'utiliser la même clé sur plusieurs appareils, puis créez un nouveau répertoire cloud à synchroniser",
|
||||||
|
|
|
||||||
|
|
@ -960,7 +960,7 @@
|
||||||
"129": "雲端數據已經損壞,請參考<a href=\"https://ld246.com/article/1658499492287\" target=\"_blank\">這裡</a>解決該問題",
|
"129": "雲端數據已經損壞,請參考<a href=\"https://ld246.com/article/1658499492287\" target=\"_blank\">這裡</a>解決該問題",
|
||||||
"130": "正在啟動新版本安裝程序...",
|
"130": "正在啟動新版本安裝程序...",
|
||||||
"131": "不支持該操作,請到雲端存儲提供商管理控制台進行操作",
|
"131": "不支持該操作,請到雲端存儲提供商管理控制台進行操作",
|
||||||
"132": "TODO",
|
"132": "當前搜索方式下不支持替換操作,請使用 [文本] 或 [正則表達式] 搜索方式",
|
||||||
"133": "TODO",
|
"133": "TODO",
|
||||||
"134": "為避免剛恢復的數據被同步覆蓋,數據同步功能已被自動暫停",
|
"134": "為避免剛恢復的數據被同步覆蓋,數據同步功能已被自動暫停",
|
||||||
"135": "無法解密數據。請確保多個設備上使用相同的密鑰,然後創建新的雲端目錄進行同步",
|
"135": "無法解密數據。請確保多個設備上使用相同的密鑰,然後創建新的雲端目錄進行同步",
|
||||||
|
|
|
||||||
|
|
@ -960,7 +960,7 @@
|
||||||
"129": "云端数据已经损坏,请参考<a href=\"https://ld246.com/article/1658499492287\" target=\"_blank\">这里</a>解决该问题",
|
"129": "云端数据已经损坏,请参考<a href=\"https://ld246.com/article/1658499492287\" target=\"_blank\">这里</a>解决该问题",
|
||||||
"130": "正在启动新版本安装程序...",
|
"130": "正在启动新版本安装程序...",
|
||||||
"131": "不支持该操作,请到云端存储提供商管理控制台进行操作",
|
"131": "不支持该操作,请到云端存储提供商管理控制台进行操作",
|
||||||
"132": "TODO",
|
"132": "当前搜索方式下不支持替换操作,请使用 [文本] 或 [正则表达式] 搜索方式",
|
||||||
"133": "TODO",
|
"133": "TODO",
|
||||||
"134": "为避免刚恢复的数据被同步覆盖,数据同步功能已被自动暂停",
|
"134": "为避免刚恢复的数据被同步覆盖,数据同步功能已被自动暂停",
|
||||||
"135": "无法解密数据。请确保多个设备上使用相同的密钥,然后创建新的云端目录进行同步",
|
"135": "无法解密数据。请确保多个设备上使用相同的密钥,然后创建新的云端目录进行同步",
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,17 @@ func findReplace(c *gin.Context) {
|
||||||
|
|
||||||
k := arg["k"].(string)
|
k := arg["k"].(string)
|
||||||
r := arg["r"].(string)
|
r := arg["r"].(string)
|
||||||
|
methodArg := arg["method"]
|
||||||
|
var method int // 0:文本,1:查询语法,2:SQL,3:正则表达式
|
||||||
|
if nil != methodArg {
|
||||||
|
method = int(methodArg.(float64))
|
||||||
|
}
|
||||||
idsArg := arg["ids"].([]interface{})
|
idsArg := arg["ids"].([]interface{})
|
||||||
var ids []string
|
var ids []string
|
||||||
for _, id := range idsArg {
|
for _, id := range idsArg {
|
||||||
ids = append(ids, id.(string))
|
ids = append(ids, id.(string))
|
||||||
}
|
}
|
||||||
err := model.FindReplace(k, r, ids)
|
err := model.FindReplace(k, r, ids, method)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
ret.Code = -1
|
ret.Code = -1
|
||||||
ret.Msg = err.Error()
|
ret.Msg = err.Error()
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package model
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"path"
|
"path"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -165,8 +166,13 @@ func SearchRefBlock(id, rootID, keyword string, beforeLen int) (ret []*Block, ne
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func FindReplace(keyword, replacement string, ids []string) (err error) {
|
func FindReplace(keyword, replacement string, ids []string, method int) (err error) {
|
||||||
keyword = strings.Trim(keyword, "\"") // FTS 字符串需要去除双引号
|
// method:0:文本,1:查询语法,2:SQL,3:正则表达式
|
||||||
|
if 1 == method || 2 == method {
|
||||||
|
util.PushMsg(Conf.Language(132), 5000)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if keyword == replacement {
|
if keyword == replacement {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -194,40 +200,90 @@ func FindReplace(keyword, replacement string, ids []string) (err error) {
|
||||||
switch n.Type {
|
switch n.Type {
|
||||||
case ast.NodeDocument:
|
case ast.NodeDocument:
|
||||||
title := n.IALAttr("title")
|
title := n.IALAttr("title")
|
||||||
if strings.Contains(title, keyword) {
|
if 0 == method {
|
||||||
renameRootTitles[n.ID] = strings.ReplaceAll(title, keyword, replacement)
|
if strings.Contains(title, keyword) {
|
||||||
renameRoots = append(renameRoots, n)
|
renameRootTitles[n.ID] = strings.ReplaceAll(title, keyword, replacement)
|
||||||
|
renameRoots = append(renameRoots, n)
|
||||||
|
}
|
||||||
|
} else if 3 == method {
|
||||||
|
r, _ := regexp.Compile(keyword)
|
||||||
|
if nil != r && r.MatchString(title) {
|
||||||
|
renameRootTitles[n.ID] = r.ReplaceAllString(title, replacement)
|
||||||
|
renameRoots = append(renameRoots, n)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case ast.NodeText, ast.NodeLinkDest, ast.NodeLinkText, ast.NodeLinkTitle, ast.NodeCodeSpanContent, ast.NodeCodeBlockCode, ast.NodeInlineMathContent, ast.NodeMathBlockContent:
|
case ast.NodeText, ast.NodeLinkDest, ast.NodeLinkText, ast.NodeLinkTitle, ast.NodeCodeSpanContent, ast.NodeCodeBlockCode, ast.NodeInlineMathContent, ast.NodeMathBlockContent:
|
||||||
if bytes.Contains(n.Tokens, []byte(keyword)) {
|
if 0 == method {
|
||||||
n.Tokens = bytes.ReplaceAll(n.Tokens, []byte(keyword), []byte(replacement))
|
if bytes.Contains(n.Tokens, []byte(keyword)) {
|
||||||
|
n.Tokens = bytes.ReplaceAll(n.Tokens, []byte(keyword), []byte(replacement))
|
||||||
|
}
|
||||||
|
} else if 3 == method {
|
||||||
|
r, _ := regexp.Compile(keyword)
|
||||||
|
if nil != r && r.MatchString(string(n.Tokens)) {
|
||||||
|
n.Tokens = []byte(r.ReplaceAllString(string(n.Tokens), replacement))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case ast.NodeTextMark:
|
case ast.NodeTextMark:
|
||||||
if n.IsTextMarkType("code") {
|
if n.IsTextMarkType("code") {
|
||||||
escapedKey := html.EscapeString(keyword)
|
escapedKey := html.EscapeString(keyword)
|
||||||
if strings.Contains(n.TextMarkTextContent, escapedKey) {
|
if 0 == method {
|
||||||
n.TextMarkTextContent = strings.ReplaceAll(n.TextMarkTextContent, escapedKey, replacement)
|
if strings.Contains(n.TextMarkTextContent, escapedKey) {
|
||||||
|
n.TextMarkTextContent = strings.ReplaceAll(n.TextMarkTextContent, escapedKey, replacement)
|
||||||
|
}
|
||||||
|
} else if 3 == method {
|
||||||
|
r, _ := regexp.Compile(escapedKey)
|
||||||
|
if nil != r && r.MatchString(n.TextMarkTextContent) {
|
||||||
|
n.TextMarkTextContent = r.ReplaceAllString(n.TextMarkTextContent, replacement)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if bytes.Contains(n.Tokens, []byte(keyword)) {
|
if 0 == method {
|
||||||
n.TextMarkTextContent = strings.ReplaceAll(n.TextMarkTextContent, keyword, replacement)
|
if bytes.Contains(n.Tokens, []byte(keyword)) {
|
||||||
|
n.TextMarkTextContent = strings.ReplaceAll(n.TextMarkTextContent, keyword, replacement)
|
||||||
|
}
|
||||||
|
} else if 3 == method {
|
||||||
|
r, _ := regexp.Compile(keyword)
|
||||||
|
if nil != r && r.MatchString(n.TextMarkTextContent) {
|
||||||
|
n.TextMarkTextContent = r.ReplaceAllString(n.TextMarkTextContent, replacement)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(n.TextMarkTextContent, keyword) {
|
if 0 == method {
|
||||||
n.TextMarkTextContent = strings.ReplaceAll(n.TextMarkTextContent, keyword, replacement)
|
if strings.Contains(n.TextMarkTextContent, keyword) {
|
||||||
}
|
n.TextMarkTextContent = strings.ReplaceAll(n.TextMarkTextContent, keyword, replacement)
|
||||||
if strings.Contains(n.TextMarkInlineMathContent, keyword) {
|
}
|
||||||
n.TextMarkInlineMathContent = strings.ReplaceAll(n.TextMarkInlineMathContent, keyword, replacement)
|
if strings.Contains(n.TextMarkInlineMathContent, keyword) {
|
||||||
}
|
n.TextMarkInlineMathContent = strings.ReplaceAll(n.TextMarkInlineMathContent, keyword, replacement)
|
||||||
if strings.Contains(n.TextMarkInlineMemoContent, keyword) {
|
}
|
||||||
n.TextMarkInlineMemoContent = strings.ReplaceAll(n.TextMarkInlineMemoContent, keyword, replacement)
|
if strings.Contains(n.TextMarkInlineMemoContent, keyword) {
|
||||||
}
|
n.TextMarkInlineMemoContent = strings.ReplaceAll(n.TextMarkInlineMemoContent, keyword, replacement)
|
||||||
if strings.Contains(n.TextMarkATitle, keyword) {
|
}
|
||||||
n.TextMarkATitle = strings.ReplaceAll(n.TextMarkATitle, keyword, replacement)
|
if strings.Contains(n.TextMarkATitle, keyword) {
|
||||||
}
|
n.TextMarkATitle = strings.ReplaceAll(n.TextMarkATitle, keyword, replacement)
|
||||||
if strings.Contains(n.TextMarkAHref, keyword) {
|
}
|
||||||
n.TextMarkAHref = strings.ReplaceAll(n.TextMarkAHref, keyword, replacement)
|
if strings.Contains(n.TextMarkAHref, keyword) {
|
||||||
|
n.TextMarkAHref = strings.ReplaceAll(n.TextMarkAHref, keyword, replacement)
|
||||||
|
}
|
||||||
|
} else if 3 == method {
|
||||||
|
r, _ := regexp.Compile(keyword)
|
||||||
|
if nil != r {
|
||||||
|
if r.MatchString(n.TextMarkTextContent) {
|
||||||
|
n.TextMarkTextContent = r.ReplaceAllString(n.TextMarkTextContent, replacement)
|
||||||
|
}
|
||||||
|
if r.MatchString(n.TextMarkInlineMathContent) {
|
||||||
|
n.TextMarkInlineMathContent = r.ReplaceAllString(n.TextMarkInlineMathContent, replacement)
|
||||||
|
}
|
||||||
|
if r.MatchString(n.TextMarkInlineMemoContent) {
|
||||||
|
n.TextMarkInlineMemoContent = r.ReplaceAllString(n.TextMarkInlineMemoContent, replacement)
|
||||||
|
}
|
||||||
|
if r.MatchString(n.TextMarkATitle) {
|
||||||
|
n.TextMarkATitle = r.ReplaceAllString(n.TextMarkATitle, replacement)
|
||||||
|
}
|
||||||
|
if r.MatchString(n.TextMarkAHref) {
|
||||||
|
n.TextMarkAHref = r.ReplaceAllString(n.TextMarkAHref, replacement)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ast.WalkContinue
|
return ast.WalkContinue
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue