Regex 如何查找和替换特定字符,但仅当它位于引号中时?
问题: 我有数千个文档,其中包含我不想要的特定字符。例如,字符Regex 如何查找和替换特定字符,但仅当它位于引号中时?,regex,string,visual-studio-code,Regex,String,Visual Studio Code,问题: 我有数千个文档,其中包含我不想要的特定字符。例如,字符a。这些文档包含各种字符,但我要替换的a位于双引号或单引号内 我想找到并替换它们,我认为需要使用Regex。我正在使用VSCode,但我愿意接受任何建议 我的尝试: 我能够找到以下正则表达式来匹配包含()中的值的特定字符串 然而,这只是强调了整个报价。我只想突出显示角色 任何解决方案,也许是regex之外的,都是受欢迎的 成果范例: 给定字符为a,查找替换为b 有人曾经告诉我“苹果”对你有好处=>有人曾经告诉我“苹果”对你有好处 “土
a
。这些文档包含各种字符,但我要替换的a
位于双引号或单引号内
我想找到并替换它们,我认为需要使用Regex。我正在使用VSCode,但我愿意接受任何建议
我的尝试:
我能够找到以下正则表达式来匹配包含()
中的值的特定字符串
然而,这只是强调了整个报价。我只想突出显示角色
任何解决方案,也许是regex之外的,都是受欢迎的
成果范例:
给定字符为a
,查找替换为b
有人曾经告诉我“苹果”对你有好处
=>有人曾经告诉我“苹果”对你有好处
“土豚”做好烤肉串
=>“土豚”做好烤肉串
当他妈妈告诉他在吃土豚肉时,男孩说“啊!”当他妈妈告诉他在吃土豚肉时,男孩说“bbbh”
/(["'])(.*?)(a)(.*?\1)/g
使用替换模式:
$1$2$4
据我所知,VS代码使用与JavaScript相同的正则表达式引擎,这就是我用JS编写示例的原因
问题是,如果在一组引号中有多个a,那么它将很难提取出正确的值,因此后面需要某种代码,或者您敲打“替换”按钮直到找不到更多匹配项,以递归模式并去掉引号之间的所有a
let regex=/([“')(.*?)(a)(.*?\1)/g,
subst=`1$2$4`,
str=`“a”
“helapke”
不匹配-AAAAAA
“这就是世界末日”
“不是用火”
“阿巴”
“阿巴”,
“我能吃到奶酪汉堡”
“这不是一场比赛”
`;
//循环以除去引号中的多个a
while(str.match(regex)){
str=str.replace(regex,subst);
}
const result=str;
控制台日志(结果)代码>首先需要考虑以下几点:
一个引号内可能有多个a
字符
每个引号(使用单引号或双引号)由一个开始引号字符、一些文本和相同的结束引号字符组成。一种简单的方法是假设当引号字符按顺序计数时,奇数字符是开始引号,偶数字符是结束引号
在第2点之后,是否允许使用单引号字符串可能值得进一步思考。请参见以下示例:很遗憾没有引用“此引用文本”。
在这里,简单的方法会认为有两个引用字符串:s a shame
和is
。另一个:这不是一个引文……“这是”和“不清楚这个引文的结尾”
。我避免尝试解决这些复杂问题,而是采用下面的简单方法
坏消息是,第1点出现了一点问题,因为后面带有通配符重复字符的捕获组(例如,(.*)
)将只捕获最后捕获的“东西”。但好消息是,有一种方法可以在一定范围内解决这个问题。许多正则表达式引擎将允许多达99个捕获组(*)。因此,如果我们可以假设每个报价中不超过99个a
s(UPDATE…或者即使我们不能-参见步骤3),我们可以执行以下操作
(*)不幸的是,我的第一个调用端口Notepad++不支持,它最多只允许9个。不确定VS代码。但是(用于下面的在线演示)没有
TL;医生-怎么办?
搜索以下以下以下以下以下代码搜索搜索::<代码>搜索搜索搜索::((((^^a a“““““碎片碎片碎片)搜索搜索搜索搜索搜索搜索::::::::::::::::::::::::::::::::(((^^a a““““碎片碎片碎片)搜索搜索搜索搜索搜索搜索搜索搜索搜索搜索:::((((((…………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………a*([^a]*)a*([^a]*)a*([^a]*)a*([^a]*)a*([^a]*)a*([^a]*)a*([^a]*)([^a]*)a*([^a]*)a*([^a]*)a*([^a]*)([^a]*)a*)([^a]*)a*)([^a]*)a*)([^a]*)a]*)([^a]*)*)(^^a碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片a*([^a”]*)a*([^a”]*)a*([^a”]*)a*([^a”]*)a*([^a”]*)a*([^a”]*)a*([^a”]*)a*([^a”]*)([^a”]*)a*([^a”]*)a*([^a”]*)a*([^a”]*)a*)([^a”]*)a*)([^a”]*)a*)([^a]*)([^a”]*)(^^a碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片碎片a*([^a”]*)a*([^a”]*)a*([^a”]*)a*([^a”]*)a*([^a”]*)a*([^a”]*)a*([^a”]*)a*([^a”]*)([^a”]*)a*([^a”]*)([^a”]*)a*([^a”]*)a*([^a”]*)a*)a*([^a”]*)a*)a*
$1$2$4
a(?=[^"]*"[^"]*(?:"[^"]*"[^"]*)*$)
a(?=[^"\\]*(?:\\.[^"\\]*)*"[^"\\]*(?:\\.[^"\\]*)*(?:"[^"\\]*(?:\\.[^"\\]*)*"[^"\\]*(?:\\.[^"\\]*)*)*$)
(?:"|\G(?<!")(?!\A))(?<r>[^a"\\]*+(?>\\.[^a"\\]*)*+)\K(a|"(*SKIP)(*F))(?(?=((?&r)"))\3)
^ ^ ^
(?: # 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
(?<="[^"\n]*)a(?=[^"\n]*")
(?<!^[^"\n]*(?:(?:"[^"\n]*){2})+)(?<="[^"\n]*)a(?=[^"\n]*")
(?<!^[^"\n]*(?:(?:"(?:[^"\\\n]|\\.)*){2})+)(?<="[^"\n]*)a(?=[^"\n]*")
(?<!\A[^"]*(?:(?:"(?:[^"\\]|\\.)*){2})+)(?<="[^"]*)a(?=[^"]*")
(?s) # Dot-all inine modifier
(?:
^ # BOS
( # (1 start), Find first quote from BOS (written back)
[^"]*
(?: # --- Cluster
" [^"a]* # Inside quotes with no 'a'
(?= " )
" [^"]* # Between quotes, get up to next quote
(?= " )
)* # --- End cluster, 0 to many times
" [^"a]* # Inside quotes, will be an 'a' ahead of here
# to be sucked up by this match
) # (1 end)
| # OR,
(?! ^ ) # Not-BOS
\G # Continue where left off from last match.
# Must be an 'a' at this point
)
a # The 'a' to be replaced
( # (2 start), Up to the next 'a' (to be written back)
[^"a]*
(?: # --------------------
(?= a .*? " ) # If stopped before 'a', must be a quote ahead
| # or,
(?: # --------------------
" [^"]* $ # If stopped at a quote, check for EOS
| # or,
" [^"]* # Between quotes, get up to next quote
(?= " )
(?: # --- Cluster
" [^"a]* # Inside quotes with no 'a'
(?= " )
" [^"]* # Between quotes
(?= " )
)* # --- End cluster, 0 to many times
" [^"a]* # Inside quotes, will be an 'a' ahead of here
# to be sucked up on the next match
) # --------------------
) # --------------------
) # (2 end)