如何在Ruby中解析包含通配符和字符类的字符串?

时间:2009-04-22 09:29:11

标签: ruby parsing

我想编写一个脚本,它接受一个可能如下所示的参数:

abc(ag)de*

abc是文字字符。

(ag)表示“a'a'或'g'”。

*表示任何一个字母或数字。

我希望脚本创建一个包含输入可能代表的所有可能字符串的数组。 (目的是检查它们是否可用域名。)

输入也可能类似abc(ag)de(mnlop),其中不仅仅是字符类。

似乎第一个任务是将其拆分为数组或数组,所以第一个例子就是......

[
  ['a'],
  ['b'],
  ['c'],
  ['a', 'g'],
  ['d'],
  ['e'],
  [
    'a', 'b', 'c', 'd', 'e', 'f', 'g',
    # etc...
  ]
]

这是我被卡住的地方。我不知道怎么把它分成这样的碎片。

有关如何处理它的任何建议?

3 个答案:

答案 0 :(得分:5)

这是一个非常紧凑的解决方案。它并没有针对性能进行优化,这会对您提供的模式施加一些限制,例如:太多的通配符可能不是最好的主意。

这是代码

input1 = "abc(ag)de*"
input2 = "abc(ag)de(mnlop)"

class Array
  def append_suffixes!(suffixes)
    self.replace suffixes.map { |a| self.map { |p| p + a }}.flatten
  end
end

def generate_combinations(pattern)
  combinations = [""]
  pattern.scan(/\(([^)]+)\)|(\*)|(\w+)/) do |group,wildcard,other|
    new_suffixes = case
      when group    : group.split('')
      when wildcard : [*'a'..'z']
      when other    : other
      else raise "Unknown match!"
    end
    combinations.append_suffixes! new_suffixes
  end
  combinations
end

p generate_combinations(input1)
p generate_combinations(input2)
p generate_combinations("**").size

运行上面代码的输出是(稍加编辑):

["abcadea", "abcgdea", "abcadeb", "abcgdeb", "abcadec", 
 "abcgdec", "abcaded", "abcgded", "abcadee", "abcgdee", 
 "abcadef", "abcgdef", "abcadeg", "abcgdeg", "abcadeh", 
 "abcgdeh", "abcadei", "abcgdei", "abcadej", "abcgdej", 
 "abcadek", "abcgdek", "abcadel", "abcgdel", "abcadem", 
 "abcgdem", "abcaden", "abcgden", "abcadeo", "abcgdeo", 
 "abcadep", "abcgdep", "abcadeq", "abcgdeq", "abcader", 
 "abcgder", "abcades", "abcgdes", "abcadet", "abcgdet", 
 "abcadeu", "abcgdeu", "abcadev", "abcgdev", "abcadew", 
 "abcgdew", "abcadex", "abcgdex", "abcadey", "abcgdey", 
 "abcadez", "abcgdez"]

["abcadem", "abcgdem", "abcaden", "abcgden", "abcadel", 
 "abcgdel", "abcadeo", "abcgdeo", "abcadep", "abcgdep"]

676 # The number of two letter words i.e. 26*26

如果您对上述代码有任何疑问,请随时询问。

答案 1 :(得分:1)

如果你的*只代表一个字符,那么我想这至少是可以解决的。如果它意味着“零或更多任何一个角色”,那么感觉好像你的解决方案空间接近无限,因此很难作为一个实际的具体价值返回。

我想我会通过某种方式分割变量部分,计算每个变量支持多少变量,然后(概念上)以嵌套方式循环所有变量,为最内层循环的每次迭代形成一个输出字符串。

对于“abc(ag)de *”的示例字符串,这可归结为此(Python-ish伪代码,我的Ruby不适合公共使用):

results = []
for x in "ag":
  for y in "abcdefghijklmnopqrstuvwxyz":
    results.append("abc%sde%s" % (x, y))

最后一行中字符串中的%s是格式说明符,s只表示“字符串”,并且在该位置插入字符串后,将导致从%运算符右侧的元组对应的值。

答案 2 :(得分:1)

你基本上要求的是采用正则表达式并生成它匹配的所有字符串。

那是Ruby Quiz #143。看看左侧的解决方案。