首页 > 解决方案 > 域或主机名的正则表达式模式,或者可能是匹配模式的最佳方式

问题描述

这是一个示例域名 FQDN,如何匹配短主机名后面的域名?而不是对域名进行模式匹配?非常感谢您的建议。

host1.dept1.domain.com
host2.domain.com
host3.domain3.com

标签: arraysregexruby

解决方案


需要考虑的事情:

require 'fruity'

nodes = %w[
  host1.dept1.domain.com
  host2.domain.com
  host3.domain3.com
]

def your_way_gsub(listnode)
  nodes = []
  listnode.each do |listnodes|
    nodes << listnodes.gsub(/^(?:[\w]+)(.)/, '')
  end
  nodes
end

def your_way_sub(listnode)
  nodes = []
  listnode.each do |listnodes|
    nodes << listnodes.sub(/^(?:[\w]+)(.)/, '')
  end
  nodes
end

def my_way_split_join(ary)
  ary.map { |s|
    s.split('.')[1..-1].join('.')
  }
end

def my_way_regex(ary)
  ary.map { |s|
    s[/^[^.]+\.(.+)$/, 1]
  }
end

检查他们是否在做正确的事情:

your_way_gsub(nodes)     # => ["dept1.domain.com", "domain.com", "domain3.com"]
your_way_sub(nodes)      # => ["dept1.domain.com", "domain.com", "domain3.com"]
my_way_split_join(nodes) # => ["dept1.domain.com", "domain.com", "domain3.com"]
my_way_regex(nodes)      # => ["dept1.domain.com", "domain.com", "domain3.com"]

并运行基准测试:

compare do
  _your_way_gsub { your_way_gsub(nodes) }
  _your_way_sub { your_way_sub(nodes) }
  _my_way_split_join { my_way_split_join(nodes) }
  _my_way_regex { my_way_regex(nodes) }
end

# >> Running each test 2048 times. Test will take about 1 second.
# >> _my_way_regex is faster than _your_way_sub by 19.999999999999996% ± 10.0%
# >> _your_way_sub is faster than _my_way_split_join by 39.99999999999999% ± 10.0%
# >> _my_way_split_join is faster than _your_way_gsub by 2x ± 0.1

根据定义,主机名可以包括a.. z0..9和:.-

主机名的每个元素的长度必须为 1 到 63 个字符,整个主机名(包括点)的长度最多为 253 个字符。主机名的有效字符是从 a 到 z 的 ASCII(7) 字母、从 0 到 9 的数字以及连字符 (-)。主机名不能以连字符开头。

如果名称类似于"legal-hostname.domain.tld"因为\w实际上[a-z0-9_]在正则表达式中的含义,则您的代码会在连字符上显示:

/\w/ - A word character ([a-zA-Z0-9_])

nodes = %w[
  legal-hostname.domain.tld
]

your_way_gsub(nodes)     # => ["hostname.domain.tld"]
your_way_sub(nodes)      # => ["hostname.domain.tld"]
my_way_split_join(nodes) # => ["domain.tld"]
my_way_regex(nodes)      # => ["domain.tld"]

gsubsub相似,但是,给定相同的模式和输入字符串,gsub将始终运行一次迭代以搜索任何其他匹配项。在一个短字符串中搜索一次这没什么大不了的,但是在一个大字符串中或迭代许多字符串时会产生很大的不同。不要gsub用作包罗万象,因为它不是。这两种工具都在工具箱中占有一席之地,使用错误的工具可能会导致问题。

正则表达式是一件很棒的事情,但它们并不是击中我们想做的每一项任务的金锤。引擎很灵活,当我们拆分字符串时,模式可以节省大量时间,但是您必须仔细测试和基准测试,因为写得不好的模式可能会在您的代码中打开很难诊断的漏洞,或者更糟的是,可以导致您的代码缓慢爬行,因为没有告诉引擎如何有效地扫描。

也就是说,模式的丰富性值得研究。你可以用它们做一些令人惊奇的事情,但总是尝试不同的方法来完成相同的任务,不要假设一种更快,检查一下。

请参阅“正则表达式:现在你有两个问题”以获得很好的讨论。有关更多信息,请参阅 Ruby 的Regexp 文档


推荐阅读