【问题标题】:Selectively replace words with regular expressions有选择地用正则表达式替换单词
【发布时间】:2015-07-16 12:31:01
【问题描述】:

是否可以用正则表达式选择性地替换某些单词?

我的文档包含如下几行:

<type>xxx</type>

其中xxx可以是bugimprovementnewfeature和其他几个值。

我想把它转换成:

"kind":"yyy",

其中yyy = xxx除了 improvement 应替换为 enhancementnewfeature 应替换为 proposal。在所有其他情况下,yyy 应与 xxx 相同。

直接的正则表达式会将&lt;type&gt;([^&lt;]+)&lt;/type&gt; 替换为"kind":"$1",,但是否可以同时替换这两个特殊词?

我相信我正在使用 PCRE 引擎。

【问题讨论】:

  • 不,不可能进行 1 次替换操作。您很可能会通过变通方法获得答案。
  • 你使用什么语言?
  • 正则表达式语言是 PCRE。我没有使用编程语言,只是使用高级文本编辑器在长代码文件中进行替换。
  • 那么什么是文本编辑器?
  • 文本编辑器是Sublime Text,稳定频道,build 3065。

标签: regex sublimetext3 pcre


【解决方案1】:

不能将条件语句放在替换字符串中或将数据(不在字符串中)存储在模式本身中。

sublimetext 更简单的方法显然是分几个步骤进行(之前替换特殊字符串,之后替换一般情况)。好的方法是使用编程语言和 xml 解析器。

但是可以通过一个技巧一次性完成 replaceAll:

1) 在文件的最后添加这一行(在新行中):

#improvement:enhancement#newfeature:proposal#"kind":"

2) 使用这种模式:

<type>(?|([^<]+)</type>(?=(?:.*\R)++#(?>[^:]+:[^#]+#)??\1:([^#]++).*#((.).*))|(([^<]+))</type>(?=(?:.*\R)++.*#((.).*)))|\R.*\z

用这个替换:

$3$2$4

$3 代表"kind":" 或无,$2 代表enhancementproposalxxx 或无,$4 代表" 或无。)

3) 全部替换

demo

想法很简单:将所有替换内容放在字符串本身中,并在模式中使用分支重置(?|.(..).|.(..).)(每个备选方案中的此功能捕获组具有相同的数字) .添加的行会被自动删除。

注意:如果你有两个以上的特殊术语要替换,请完成最后一行(但"kind":"必须留在最后),并将模式中的??更改为@987654336 @。

图案细节:

<type>
(?|                        # open a branch reset group
                           # first branch: the special terms
    ([^<]+)                # capture the term in group 1
    </type>
    (?=                    # open a lookahead (nothing is consumed inside it)
        (?:.*\R)++ #       # reach the last line
        (?>[^:]+:[^#]+#)?? # skip a couple of term:repl if needed
        \1                 # until the content of group 1 is found
        : ([^#]++)         # capture the corresponding replacement
        .* #               # reach the last #
        ((.).*)            # capture '"kind":"' in group 3 and '"' in group 4
    )                      # close the lookahead
  |                        # OR second branch: the general case
    (([^<]+))              # capture the term in group 1 and 2
                           # (to have the same number than the previous branch)
    </type>
    (?=                    # open a lookahead
        (?:.*\R)++         # same thing than the previous branch
        .* #               # but this time only '"kind":"' and '"'
        ((.).*)            # are needed
    )
)                          # close the branch reset group
|                          # OR
\R.*\z                     # the last line (in this case all the
                           # groups are empty) 

\R 是几种换行符的别名(无论系统如何)。

(?&gt;....) 是一个原子团。

++*+?+ 是所有格量词。

\z 是字符串结尾的锚。

【讨论】:

  • 哇,这真是一个很棒的解决方案。那里有几个运算符我需要了解更多信息,但这绝对是我的入门!非常感谢。
  • 问个简单的问题:++(?&gt;)?? 是性能优化,分别与 +(?:)*? 达到相同的结果,对吗?
  • @Peter:没有一般规则。例如(?:.*\R)++ 确保后面的内容在最后一行,而(?:.*\R)+ 则没有,因为回溯是可能的。 ??(或*?)是一种选择,我更喜欢一对一对地推进,直到找到好的一对,而不是匹配所有对,然后一个一个地回溯找到它。 (?&gt;...) 确实提高了性能,但主要目标是一对一对地“移动”,而不需要处理包含该组的内容((?:...) 正则表达式引擎记录组中所有字符的每个回溯位置,但不使用 @ 987654356@)
  • @Peter: ?? 只是? 的非贪婪版本,*?* 的非贪婪版本。看看 www.rexegg.com,其中包含对贪婪/非贪婪、所有格量词/原子组等概念的很好解释。
猜你喜欢
  • 1970-01-01
  • 2015-09-03
  • 1970-01-01
  • 2022-12-10
  • 2020-01-06
  • 1970-01-01
  • 2010-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多