我正在尝试将数字字符按字符串中的位置进行匹配。例如,在字符串"1234567"
中,我想选择第二个到第四个字符:"234"
。 "D9873Y.31"
也应该出现"987"
。你有什么建议吗?
答案 0 :(得分:5)
您不需要正则表达式,只需使用String#[]
:
s = '1234567'
s[1..3] #=> "234"
s = 'D9873Y.31'
s[1..3] #=> "987"
答案 1 :(得分:2)
你可以使用正则表达式,并且模式足够灵活,可以用不同的方式编写它们。我试着让它们变得非常简单,因为它们的神秘性可以成为维护的噩梦:
"1234567"[/^.(.{3})/, 1]
=> "234"
"D9873Y.31"[/^.(.{3})/, 1]
=> "987"
"1234567".match(/^.(.{3})/)[1]
=> "234"
"D9873Y.31".match(/^.(.{3})/)[1]
=> "987"
您还可以利用named-captures:
/^.(?<chars2_4>.{3})/ =~ "1234567"
chars2_4
=> "234"
/^.(?<chars2_4>.{3})/ =~ "D9873Y.31"
chars2_4
=> "987"
所有这一切都很好,但是深入挖掘和学习它们非常重要,因为,做错了,你可以抓住错误的数据,或者更糟糕的是,通过让正则表达式引擎非常努力地做一些简单的事情来真正减慢你的脚本速度
例如,我上面使用了^
。 ^
匹配行的开头,该行是字符串的开头,紧跟在换行符后面的字符。对于短字符串来说这是可以的,但是长字符串,特别是嵌入式新行可能会减慢引擎速度。相反,您可能想要使用\A
。相同的情况适用于$
或\Z
或\z
。这来自Regexp文档部分的“Anchors”:
^
- 匹配行首$
- 匹配行尾\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)
答案 2 :(得分:1)
你可以使用带锚的lookbehind来做到这一点,例如:
(?<=^.{2}).{3}
会给你345