【问题标题】:How to know if a match is adjacent to the previous match如何知道一场比赛是否与前一场比赛相邻
【发布时间】:2012-08-25 04:04:21
【问题描述】:

在类似的结构中

string.scan(regex){...}

string.gsub(regex){...}

如何检查循环循环的匹配是否与原始字符串中的前一个相邻?例如,在

"abaabcaaab".scan(/a+b/){|match|
    ...
    continued = ...
    ...
}

将有三个匹配项"ab""aab""aaab"。在每个循环中,我希望他们将变量 continued 分别设为 falsetruefalse,因为 "ab" 是第一个匹配循环,"aab" 与之相邻,@987654334 @在下一场比赛之前中断"aaab"

"ab" #=> continued = false
"aab" #=> continued = true
"aaab" #=> continued = false

origuruma 中是否有一个锚点指向上一个匹配位置的结尾?如果是这样,那可以在正则表达式中使用。如果没有,我可能需要使用MatchData#offset 之类的东西。并在循环中进行一些计算。

顺便问一下,origuruma 正则表达式中的\G 是什么?我的印象是它可能是我想要的锚,但我不确定它是什么。

【问题讨论】:

  • 不幸的是,scangsub 都不能与 MatchData 对象一起使用。您可以编写自己的scan,这很容易,只需使用match 及其偏移支持。
  • @muistooshort $~$~.offset 可用于 scan。例如,` "aaaaaaaaaa".scan(/./){|x| p $~.offset(0)}` 没问题。
  • 谢谢,我一直无法记住所有的魔法全局变量。我仍然认为如果scan 给你一个 MatchData 会更好,命名的捕获组有点'方便。 PS:geocities.jp/kosako3/oniguruma/doc/RE.txt,我不知道这是不是最新的参考,但那是我收藏的。

标签: ruby regex ruby-1.9.3 oniguruma


【解决方案1】:

我不相信使用这些方法可以获得偏移数据。您可能必须使用Regexp#match,每次都传递该位置。返回的MatchData 对象还包含您进行任何替换等所需的所有信息。

当然,如果你在增加偏移量的同时进行字符串替换,如果替换的长度与匹配的长度不同,你必须小心。这里的一个常见模式是向后移动字符串,但我认为您无法使用这些方法遵循该模式,因此您需要调整偏移量。

编辑 |实际上,如果您在完全独立的步骤中进行替换,您将能够向后移动字符串。首先找到您需要替换的所有内容以及偏移量。接下来,以相反的顺序迭代该列表,进行替换。

【讨论】:

  • 您可以使用match 来制作scan,这比标准扫描更有意义,因为它将块传递给 MatchData 而不是简单的数组,我这样做是为了让我可以scan 使用命名的捕获组。
  • $~$~.offset 可用于 scan。例如,` "aaaaaaaaaa".scan(/./){|x| p $~.offset(0)}` 没问题。
【解决方案2】:

StringScanner 非常适合这项任务:http://corelib.rubyonrails.org/classes/StringScanner.html

require 'strscan'
s = StringScanner.new('abaabcaaab')

begin
        puts s.pos
        s.scan_until(/a+b/)
        puts s.matched
end while !s.matched.nil?

输出

0
ab
2
aab
5
aaab
10
nil

因此,您可以只跟踪最后一场比赛的长度和位置,并计算它们是否相邻。

【讨论】:

    猜你喜欢
    • 2015-09-16
    • 2016-06-05
    • 2022-11-23
    • 1970-01-01
    • 2012-03-27
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 1970-01-01
    相关资源
    最近更新 更多