【问题标题】:How do I get the index of a character as it occurs in a regular expression?如何获取正则表达式中出现的字符索引?
【发布时间】:2017-07-15 23:56:50
【问题描述】:

在 Ruby(使用 RoR 5.0.1)中,我想获取文本块中数字“2”的索引

"\n2 hel2 lo"

但是,我只想要两者的索引,前提是它前面有空格或行首,后面有空格。所以我掀起了这个小正则表达式

2.4.0 :007 > regex = /([[:space:]]|^)2([[:space:]]|\.|\))/
 => /([[:space:]]|^)2([[:space:]]|\.|\))/
2.4.0 :008 > text_content = "\n2 hel2 lo"
 => "\n2 hel2 lo"
2.4.0 :009 > text_content.index(regex)
 => 0

但显然这个正则表达式返回零,因为这是正则表达式第一次出现的地方。我想要一个返回“1”的表达式,因为 1 是“2”在正则表达式中出现的位置的索引。我该怎么做?

【问题讨论】:

  • 好吧,试试ideone.com/vwVGtA
  • text_content.index(/(?<=[\n\s])\d\s/) 可能没问题。
  • @sagarpandya82,如果我想匹配行首或数字前的空格怎么办?我尝试了 /(?
  • @Wiktor,应该先尝试过你的建议 -- /(?

标签: ruby regex ruby-on-rails-5


【解决方案1】:

您的正则表达式在字符串的开头正确匹配,但您只需要从2 开始获取模式的位置,因此,我建议将([[:space:]]|^) 部分转换为(?<![^[:space:]]) 负后视:

regex = /(?<![^[:space:]])2([[:space:].)])/
text_content = "\n2 hel2 lo"
text_content.index(regex)  
# => 1

请参阅Ruby demo

(?&lt;![^[:space:]]) 后视(匹配当前位置左侧没有非空白字符的位置)是一个零宽度断言,只会检查是否存在,文本不会比赛的一部分,因此,您将获得正确的位置。

【讨论】:

【解决方案2】:

你可以使用/(?&lt;=\s|^)2\s/:

> "\n2 hel2 lo".index(/(?<=\s|^)2\s/)
=> 1
> "2 hel2 lo".index(/(?<=\s|^)2\s/)
=> 0
> "abc 2 hel2 lo".index(/(?<=\s|^)2\s/)
=> 4
> "abc  hel2 lo".index(/(?<=\s|^)2\s/)
=> nil

注意它不会在字符串的末尾匹配:

> "abchel2 lo 2".index(/(?<=\s|^)2\s/)
=> nil

【讨论】:

    【解决方案3】:
    r = /
        (?<!\S)  # do not match a non-whitespace character (negative lookbehind)
        2        # match 2
        (?=\s)   # match a whitespace character in a positive lookahead
        /x       # free-spacing regex definition mode
    
    "\n2 hel2 lo" =~ r  #=> 1
    "42 hel 2 lo" =~ r  #=> 7
    "42 hel*2 lo" =~ r  #=> nil
    

    如果要为单字符字符串"2" 返回索引0,请将正则表达式更改为

    r = /(?<!\S)2(?!\S)/
    "2" =~ r  #=> 0`
    

    (?!\S) 是一个否定的前瞻,它规定"2" 后面不能跟非空白字符。

    如果字符串可能包含多个满足条件的"2",并且所有匹配项都需要索引,则可以使用String#scan 和刚刚给出的正则表达式(r = /(?&lt;!\S)2(?!\S)/)。 (我假设字符串末尾的 "2" 是匹配的,如果它前面有一个空格字符或者也在字符串的开头。)

    arr = []
    "\n2 302 2 2".scan(r) { arr << Regexp.last_match.begin(0) }
    arr
      # => [1, 7, 9]
    

    请参阅String#=~Regexp::last_match1MatchData#begin

    1 Regexp.last_match返回全局变量$~的值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-14
      • 1970-01-01
      • 1970-01-01
      • 2021-01-02
      • 1970-01-01
      • 2013-03-24
      • 2015-10-28
      • 1970-01-01
      相关资源
      最近更新 更多