【问题标题】:Regex that only matches on odd/even indices仅匹配奇数/偶数索引的正则表达式
【发布时间】:2015-09-17 19:02:26
【问题描述】:

是否有一个正则表达式仅在字符串从奇数或偶数索引开始时才匹配它?我的用例是一个十六进制字符串,我想在其中替换某些“字节”。

现在,当尝试匹配20(空格)时,“7209”中的20 也会匹配,即使它由字节7209 组成。在这种情况下,我仅限于 Notepad++ 的正则表达式实现,因此我无法检查匹配索引,例如在 Java 中。

我的示例输入如下所示:

324F8D8A20561205231920

我设置了一个测试页面here,正则表达式应该只匹配20的第一个和最后一个出现,因为中间的那个从一个奇数索引开始。

【问题讨论】:

  • 有什么东西可以分隔字符串的开始和结束吗?
  • 请检查20(?=(?:\d{2})+|\D|$) 是否适合您。
  • 文件的开始和结束,我认为 Notepad++ 允许至少匹配文件的结尾与 \z 不确定开始
  • @stribizhev 您发布的正则表达式匹配所有 20 岁,但遗憾的是那些不应该匹配的(例如 7209)
  • 请发布一些输入文本,没有它很难猜出模式会是什么。

标签: regex hex notepad++


【解决方案1】:

您可以使用以下正则表达式在十六进制字符串内的偶数位置匹配 20

20(?=(?:[\da-fA-F]{2})*$)

demo

我假设在这种情况下字符串没有空格。

如果值之间有空格(或任何其他符号),这可能是另一种选择(使用$1XX-like 替换字符串):

((?:.{2})*?)20

another demo

【讨论】:

  • 为什么最后会出现析取?不能更简单吗,像这样:20(?=(?:[\da-fA-F]{2})*$)
  • @BramVanroy:20(?=(?:[\da-fA-F]{2})+$|$) 确实等于20(?=(?:[\da-fA-F]{2})*$)。一开始我没有注意到示例输入字符串,并且正在研究不同的东西。那只是之前努力的残余。感谢您的关注。但是,开销只是额外的 1 个步骤。
【解决方案2】:

这似乎适用于偶数:

rx <- "^(.{2})*(20)"

strings <- c("7209","2079","9720")

grepl(rx,strings) # [1] FALSE  TRUE  TRUE

【讨论】:

  • 它只匹配我的一切,在 Notepad++ 以及 Regex101 (regex101.com/r/eV7rR9/1) 中
  • 定义奇数和偶数 -- 你的索引是从零开始还是从一开始?
  • 如果索引从 0 开始,我希望我的匹配从偶数索引(0、2、4...)开始,对于 1 索引它会是奇数。
  • 对,它匹配字符串,因为位置 20 有一个 20(偶数索引)。你想捕获整个字符串,还是只捕获 20 个?
  • 我只想捕获 20 个(以及之后的每个偶数索引的 20 个)以便之后能够替换它
【解决方案3】:

不确定 Notepad++ 将什么用于正则表达式引擎 - 我已经有一段时间没有使用它了。这适用于 javascript...

/^(?:..)*?(20)/

...

/^     # start regex
(?:    # non capturing group
..     # any character (two times)
)*?    # close group, and repeat zero or more times, un-greedily
(20)   # capture `20` in group
/      # end regex

【讨论】:

  • 你的正则表达式只匹配我最后一次出现的 20,即使在 JS 引擎中也是如此(参见regex101.com/r/rF7bS1/2
  • 它通过删除 ^ 有点工作,否则它只会匹配第一次出现,即使全局打开,但它似乎并不完全健壮,因为它在这里中断 (regex101.com/r/hY8kK7/3)
  • 它会在没有锚点的情况下中断,^$ 是必要的,但如果没有可变宽度的后视,使用 ^ 作为参考点是没有意义的。我选择了$,因为在 Notepad++ 正则表达式风格中,前瞻不是固定宽度。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多