1

我正在尝试通过数字字符在字符串中的位置来匹配它们。例如,在字符串"1234567"中,我想选择第二个到第四个字符:"234""D9873Y.31"也应该出现"987"。你有什么建议吗?

4

3 回答 3

5

你不需要正则表达式,你可以使用String#[]

s = '1234567'
s[1..3]  #=> "234"

s = 'D9873Y.31'
s[1..3]  #=> "987"
于 2013-06-12T00:53:13.210 回答
2

您可以为此使用正则表达式,并且模式足够灵活,可以用几种不同的方式编写它们。我尽量让它们保持简单,因为它们的神秘性质可能会成为维护的噩梦:

"1234567"[/^.(.{3})/, 1]
=> "234"
"D9873Y.31"[/^.(.{3})/, 1]
=> "987"

"1234567".match(/^.(.{3})/)[1]
=> "234"
"D9873Y.31".match(/^.(.{3})/)[1]
=> "987"

您还可以利用命名捕获

/^.(?<chars2_4>.{3})/ =~ "1234567"
chars2_4
=> "234"

/^.(?<chars2_4>.{3})/ =~ "D9873Y.31"
chars2_4
=> "987"

这一切都很好,但是深入研究并很好地学习它们非常重要,因为如果做错了,您可能会获取错误的数据,或者更糟的是,通过使正则表达式引擎非常努力地做一些简单的事情,真的会减慢您的脚本。

比如我^上面用的。^匹配行的开头,即字符串的开头和紧跟换行符的字符。这对于短字符串是可以的,但是长字符串,尤其是嵌入换行符的长字符串会减慢引擎的速度。相反,您可能想使用\A. 同样的情况也适用于使用$or\Z\z。这是来自“锚”的正则表达式文档部分:

  • ^- 匹配行首
  • $- 匹配行尾
  • \A- 匹配字符串的开头。
  • \Z- 匹配字符串的结尾。如果字符串以换行符结尾,则在换行符之前匹配
  • \z- 匹配字符串的结尾

这就是为什么您有时希望避免使用正则表达式,而是使用@AndrewMarshall 推荐的子字符串。

这是为什么简单的子字符串方式更可取的另一个原因:

require 'benchmark'

N = 1_000_000
Benchmark.bm(13) do |b|
  b.report('string index') { N.times {
    "1234567"[1..3]
    "D9873Y.31"[1..3]
  } }

  b.report('regex index') { N.times {
    "1234567"[/^.(.{3})/, 1]
    "D9873Y.31"[/^.(.{3})/, 1]
  } }

  b.report('match') { N.times {
    "1234567".match(/^.(.{3})/)[1]
    "D9873Y.31".match(/^.(.{3})/)[1]
  } }

  b.report('named capture') { N.times {
    /^.(?<chars2_4>.{3})/ =~ "1234567"
    /^.(?<chars2_4>.{3})/ =~ "D9873Y.31"
  } }

  b.report('look behind') { N.times {
    "1234567"[/(?<=^.{2}).{3}/, 1]
    "D9873Y.31"[/(?<=^.{2}).{3}/, 1]
  } }
end

返回:

                    user     system      total        real
string index    0.730000   0.000000   0.730000 (  0.727323)
regex index     1.370000   0.000000   1.370000 (  1.377121)
match           4.400000   0.000000   4.400000 (  4.398849)
named capture   5.240000   0.010000   5.250000 (  5.243799)
look behind     1.430000   0.000000   1.430000 (  1.437286)
于 2013-06-12T03:55:46.737 回答
1

您可以使用带有锚点的lookbehind来做到这一点,例如:

(?<=^.{2}).{3}

会给你345

于 2013-06-12T00:53:53.907 回答