将外部的单引号(')替换为双引号("),将内部的双引号(")替换为单引号(')。

5
我有类似于这样的东西:
$class = 'class="cl"' . " style=" . '"color:black,' . "background:red;" . '"';

有没有一种简单的正则表达式方法将这段代码格式化为“' '”样式?我的意思是这个:
$class = "class='cl'" . " style=" . "'color:black," . "background:red;" . "'";

我尝试了这个正则表达式:

'(?!(([^"]"){2})[^"]*$)

但是它只替换外部单引号'。我该如何将内部双引号也替换为单引号?

我想知道是否确实存在解决方案。我认为在这里嵌入条件是必要的。 - Soner from The Ottoman Empire
没有代码是不可能的。那么PythonScript脚本怎么样? - Wiktor Stribiżew
Wiktor,很可能是的。但是也许有一个带有条件替换的正则表达式解决方案(例如这个)。我找到了一个四步骤的正则表达式解决方案。 - newtonrus
3个回答

3
您可以按照以下三个步骤完成此操作,其中只有第一步需要正则表达式:
1. 将每个外部引号(无论是单引号还是双引号)一次替换为一个未使用的字符(例如µ),一对一对地: 查找: ('|")(((?!\1).)*). 替换: µ\2µ 2. 将每个剩余的双引号替换为单引号,因为根据第1步的结果它们是内部引号: 查找: " 替换: ' 3. 将第1步中的特殊字符的每个出现都替换为双引号: 查找: µ 替换: " 显然,第一个(也是唯一一个)正则表达式发挥了主要作用:它捕获它找到的第一个引号(单引号或双引号),然后捕获字符,直到下一个相同类型的引号出现(使用负条件下的\1反向引用,并最终通过.匹配第二个出现)。 这种方法的前提条件是所有外部引号都成对出现。
在启动第一个替换时,请确保插入符号位于文本的开头,以便它位于任何引号对的外部。
注:PHP(您似乎在使用它,但其他几种语言也适用)允许使用反斜杠转义字符串文字中的引号。 如果输入中存在这样的转义,则该任务会变得有点复杂,但仍然是可行的。

嗨,Trincot,如果像" style="这样的内容不需要更改,那么这会保留引号吗? - Yassin Hajaj
不,第一步会替换它们,但第三步会再次恢复它们。因此,在某种程度上,答案也是“是”。 - trincot
哦,是的,你说得对,我确实没有足够注意答案:) 顺便说一句,好答案。 - Yassin Hajaj
trincot,太好了!谢谢! :) 我猜你的解决方案是100%的。现在我正在用我的文件进行测试。 - newtonrus
trincot,您优雅的正则表达式完美地处理了我所有的源代码(20多个旧文件)。没有任何错误! :) - newtonrus
很高兴听到这个消息!;-) - trincot

2

我的解决方案是使用Notepad++中的4个正则表达式。

1. 查找所有在两个单引号之间的双引号("),并用波浪号(~)替换它们:

RegEx: (?:\G(?!^)|([^']*(?:'[^'"]*'[^']*)*'))[^"']*\K"([^"']*+(?:'(?1)|$))?
Replacement: ~$2

2. 查找所有不被两个双引号(")包围的单引号('),并用反引号(`)替换:

RegEx: '(?=(?:[^"]*"[^"]*")*[^"]*$)
Replacement: `

3. 在两个反引号(`)之间查找所有波浪线(~),并将其替换为单引号('):

RegEx: (?:\G(?!^)|([^`]*(?:`[^`~]*`[^`]*)*`))[^~`]*\K~([^~`]*+(?:`(?1)|$))?
Replacement: '$2

4. 最后一步,将所有波浪号(~)和反引号(`)替换为双引号("):

RegEx: ~|`
Replacement: "

在第一步之前,代码中不应出现波浪线和反引号。感谢链接1链接2


0
Notepad++使用Boost.Regex C++库中的正则表达式引擎。
因此,可以在替换字符串中使用条件替换
使用这个技巧,只需要一个正则表达式替换就可以完成工作。
在Notepad++中: 查找内容:
(?:"[^"]*"\s*[.;]\K)|(?:(?:(')|("))(?=[^.;]*?[.;]))

关于正则表达式,首先它匹配由双引号包围的部分,并通过\K从匹配结果中删除这些部分。然后捕获剩余的引号。

替换为:

(?1")(?2')

搜索模式:

Regular expression

例子:

这个示例字符串:

$class = 'change="this"' . 'change="this" change="this"' . 'change"this"' . '"change:this,' . " keep=this" . " keep:this;" . "dontchange='this'" . '"' . '"change_me"';

更改为:

$class = "change='this'" . "change='this' change='this'" . "change'this'" . "'change:this," . " keep=this" . " keep:this;" . "dontchange='this'" . "'" . "'change_me'";

"xxx='yyy'" 'xxx="yyy" xxx="yyy"" "xxx="yyy"' 第一个字符串可以,第二个不行,第三个也不行是因为第二个字符串。但是我同意,并且认为可以通过条件替换来解决问题。 - newtonrus
@newtonrus 嗯,单引号之间有双引号的多个组。使用纯正则表达式替换方案会遇到嵌套等问题。无论如何,我稍微改了一下我的解决方案。现在它也会处理这些情况。 - LukStorms
LukStorms,你的新正则表达式更正确了,但仍然存在错误。例如,正确的字符串是:"dontchange='this'",而你的正则表达式也会改变这样的字符串:'dontchange="this"'。 - newtonrus
在当前版本中,这已经不再改变了。 - LukStorms
@newtonrus 哈哈,这有点让我想起那个奇怪的编程语言Unreadable。之前的版本在寻找一个点号后面的字符。新版本则会寻找 .; - LukStorms
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接