如何查找和替换特定字符,但仅限于引号?

Ka *_*Mok 13 regex string visual-studio-code

问题:我有成千上万的文档,其中包含我不想要的特定字符.比如角色a.这些文档包含各种字符,但a我要替换的是双引号或单引号.

我想找到并替换它们,我认为需要使用正则表达式.我正在使用VSCode,但我对任何建议持开放态度.

我的尝试:我能够找到以下正则表达式匹配包含其中的值的特定字符串().

".*?(r).*?"
Run Code Online (Sandbox Code Playgroud)

但是,这仅突出显示整个报价.我想只突出这个角色.

任何解决方案,可能在正则表达式之外,都是受欢迎的.

示例结果:给定,字符是a,find替换为b

Somebody once told me "apples" are good for you => Somebody once told me "bpples" are good for you

"Aardvarks" make good kebabs => "Abrdvbrks" make good kebabs

The boy said "aaah!" when his mom told him he was eating aardvark => The boy said "bbbh!" when his mom told him he was eating aardvark

rev*_*evo 11

Visual Studio代码

VS Code使用JavaScript RegEx引擎来实现其查找/替换功能.这意味着与其他版本(如.NET或PCRE)相比,使用正则表达式非常有限.

幸运的是,这种味道支持前瞻和前瞻,你可以寻找但不消耗性格.因此,确保我们在带引号的字符串中的一种方法是在匹配后查找文件/主题字符串底部的引号数为奇数a:

a(?=[^"]*"[^"]*(?:"[^"]*"[^"]*)*$)
Run Code Online (Sandbox Code Playgroud)

现场演示

这将a在双引号字符串中查找s,以使单引号字符串替换所有"s '.你不能同时拥有两者.

然而,上面的正则表达式存在问题,它与双引号字符串中的转义双引号冲突.如果重要的话要匹配它们,你还有很长的路要走:

a(?=[^"\\]*(?:\\.[^"\\]*)*"[^"\\]*(?:\\.[^"\\]*)*(?:"[^"\\]*(?:\\.[^"\\]*)*"[^"\\]*(?:\\.[^"\\]*)*)*$)
Run Code Online (Sandbox Code Playgroud)

在大文件上应用这些方法可能会导致堆栈溢出,所以让我们看看更好的方法.

我正在使用VSCode,但我对任何建议持开放态度.

那很棒.然后我建议使用awk或者sed更具编程性的东西来实现你所追求的目标,或者如果你能够使用Sublime Text,就有机会以更优雅的方式解决这个问题.

崇高文本

这应该适用于具有成千上万行的大型文件,但要注意它适用于单个字符(此处a),经过一些修改可能也适用于单词或子字符串:

搜索:

(?:"|\G(?<!")(?!\A))(?<r>[^a"\\]*+(?>\\.[^a"\\]*)*+)\K(a|"(*SKIP)(*F))(?(?=((?&r)"))\3)
                           ^              ^            ^
Run Code Online (Sandbox Code Playgroud)

替换为: WHATEVER\3

现场演示

RegEx细分:

(?: # Beginning of non-capturing group #1
    "   # Match a `"`
    |   # Or
    \G(?<!")(?!\A)  # Continue matching from last successful match
                    # It shouldn't start right after a `"`
)   # End of NCG #1
(?<r>   # Start of capturing group `r`
    [^a"\\]*+   # Match anything except `a`, `"` or a backslash (possessively)
    (?>\\.[^a"\\]*)*+   # Match an escaped character or 
                        # repeat last pattern as much as possible
)\K     # End of CG `r`, reset all consumed characters
(   # Start of CG #2 
    a   # Match literal `a`
    |   # Or
    "(*SKIP)(*F)    # Match a `"` and skip over current match
)
(?(?=   # Start a conditional cluster, assuming a positive lookahead
    ((?&r)")    # Start of CG #3, recurs CG `r` and match `"`
  )     # End of condition
  \3    # If conditional passed match CG #3
 )  # End of conditional
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

三步法

最后但并非最不重要的...

匹配引号内的字符是棘手的,因为分隔符完全相同,因此在不查看相邻字符串的情况下,无法区分开关标记.您可以做的是将分隔符更改为其他内容,以便以后查找.

步骤1:

搜索: "[^"\\]*(?:\\.[^"\\]*)*"

用...来代替: $0?

第2步:

搜索: a(?=[^"\\]*(?:\\.[^"\\]*)*"?)

用你期望的任何东西替换.

第3步:

搜索: "?

没有任何东西可以替换掉所有东西.