我[sic]字符串如:
xx-xxx-xxxxx-xxx-xx
th-asd-welcome-ruk-23
name-lastname-hello
我希望匹配用连字符分隔的第二组字符,例如:xxx
,asd
,lastname
。
我试过了:
^(?:[^-]+-){1}([^-]+)
,匹配xx-xxx
(?<=-)[^\-].+(?=-)
,匹配xxx-xxxxx-xxx
我如何匹配第二个八位字节?
答案 0 :(得分:3)
正则表达式不一定是正确的表达方式。首先,我简化了任务:
STRINGS = %w[
xx-xxx-xxxxx-xxx-xx
th-asd-welcome-ruk-23
name-lastname-hello
]
STRINGS.map { |s| s.split('-')[1] }
# => ["xxx", "asd", "lastname"]
将连字符上的字符串拆分为数组,并返回每个数组中找到的第二个项目。
然后我将一个模式与scan
结合使用,只找到想要的东西:
STRINGS.map { |s| s.scan(/[^-]+/)[1] }
# => ["xxx", "asd", "lastname"]
找到所有 NOT 连字符的子字符串。
正则表达式对于某些事情很有用,但可能会增加维护问题,有时会超出其价值。它们还可以显着减慢代码速度,仅仅因为它们不是很聪明,并且添加智能需要大量测试和知道引擎将要做什么。所以,仔细去那里,测试/基准,这样你就知道模式和路径是否很快。我编写了很多代码,并指导了很多开发人员,并发现很多地方他们使用了错误的模式,引入了很难检测错误或显着减慢循环。我非常相信基准测试和测试多个路径。
例如:
require 'fruity'
STRINGS = %w[
xx-xxx-xxxxx-xxx-xx
th-asd-welcome-ruk-23
name-lastname-hello
]
compare do
split { STRINGS.map { |s| s.split('-')[1] } }
scan { STRINGS.map { |s| s.scan(/[^-]+/)[1] } }
end
# >> Running each test 1024 times. Test will take about 1 second.
# >> split is faster than scan by 4x ± 0.1
根据我的经验,我知道split
的运行速度比使用模式的scan
要快。
根据经验,我也知道模式可以非常快。测试模式的变化并提取记录:
require 'fruity'
STRINGS = %w[
xx-xxx-xxxxx-xxx-xx
th-asd-welcome-ruk-23
name-lastname-hello
]
compare do
split { STRINGS.map { |s| s.split('-')[1] } }
scan { STRINGS.map { |s| s.scan(/[^-]+/)[1] } }
slice { STRINGS.map { |s| s[/^(?:[^-]+)-([^-]+)/, 1] } }
stribizhev { STRINGS.map { |s| s.match(/(?<=-)[^-]+(?=-)/)[0] } }
end
# >> Running each test 2048 times. Test will take about 1 second.
# >> slice is faster than split by 60.00000000000001% ± 10.0%
# >> split is faster than stribizhev by 1.9x ± 0.1
# >> stribizhev is faster than scan by 80.0% ± 10.0%
所以,那个是你应该做的,以确定要遵循的路径。然后权衡维护成本:是否更容易维护s.split('-')[1]
或s[/^(?:[^-]+)-([^-]+)/, 1]
?
并且,最后一个模式超越简单split
的原因是非常快,因为模式是锚定的。锚定模式为引擎提供了一个令人难以置信的有用提示,即如何找到它所使用的所需模式。它也不需要任何回溯,这会浪费引擎的CPU时间,而引擎可以继续期待找到它想要的东西。
答案 1 :(得分:1)
答案 2 :(得分:1)
你的两个模式都太贪心了。 [^-]+
和.+
将消耗尽可能多的字符。请注意[^\-].+
并不意味着&#34;除了连字符之外的任何数量的字符&#34;。这意味着&#34;匹配1个非连字符,然后匹配任何字符,尽可能多的&#34;。
使用/(?<=-)[^-]+(?=-)/
的简单match
可以做到这一点:
puts "th-asd-welcome-ruk-23".match(/(?<=-)[^-]+(?=-)/)
或简单(没有正则表达式):
puts "th-asd-welcome-ruk-23".split("-")[1]
输出:
asd