首页 > 解决方案 > 用双引号替换单引号,当且仅当引号在特定字符串之后

问题描述

我正在使用记事本++,并使用它的查找替换对话框。
NP++ 文档指出:Notepad++ 正则表达式使用 Boost 正则表达式库 v1.70,它基于 PCRE(Perl Compatible Regular Expression)语法。参考:https ://npp-user-manual.org/docs/searching

我想做的事情应该很简单,但我是一个正则表达式新手,经过 2-3 小时的网络搜索并与在线正则表达式测试人员一起玩后,我放弃了。
我想'用双引号替换所有单引号",但当且仅当'位于一个或多个的右侧#,即在python注释内。例如,

list1 = ['apple','banana','pear'] # All 'single quotes' to LEFT of # remained unchanged.
list2 = ['tomato','carrot'] # All 'single quotes' to RIGHT of one or more # are replaced 
# # with "double quotes", like this. 

np++ 文件超过 800 行,手动替换会很乏味且容易出错。建议表示赞赏。

标签: regexnotepad++

解决方案


这个正则表达式应该做你想做的:

(^[^#]*#|(?<!^)\G)[^'\n]*\K'

它寻找一个'前面是

  1. ^[^#]*#: 行首和一些非#字符,后跟一个#; 或者
  2. (?<!^)\G: 行首或上一个匹配的结尾 ( \G),对 start of line 有一个否定的lookbehind (?<!^),这意味着它只匹配上一个匹配的结尾

然后是一些非'或换行符(以防止匹配环绕上一行的末尾)字符[^'\n]*

然后我们使用\K重置匹配,以便从匹配中丢弃之前的所有内容,并且正则表达式仅匹配'.

然后可以将其替换为".

正则表达式 101 上的演示

更新

您可以通过仅匹配非单词字符前面或后面的撇号来避免在单词中匹配撇号:

(^[^#]*#|(?<!^)\G)[^'\n]*\K('(?=\W)|(?<=\W)')

正则表达式 101 上的演示

更新 2

您还可以通过限定正则表达式的第一部分来处理字符串中存在#字符的情况,并要求事先匹配成对的引号:

(?:^[^'#]*(?:'[^']*'[^#']*)*[^'#]*#|(?<!^)\G)[^'\n]*\K(?:'(?=\W)|(?<=\W)')

正则表达式 101 上的演示


推荐阅读