以下模式的正则表达式

时间:2012-12-08 06:58:09

标签: ruby

我需要一个与此文本匹配的正则表达式:

894975||0||Lever 2000 Anti-Bacterial Bar Soap ||Health & Spa/Personal Care/Body Care/Soap

我想搜索文本,并且在两组管道之后匹配“Bar Soap”。

如果单词不符合顺序则不匹配。 我的正则表达是:

/^(?:\d+\|\|).?\|\|[^|]*?(Bar[^|]*? Soap)/i 

当“soap”首先出现并且“bar”为秒时,这不匹配。

2 个答案:

答案 0 :(得分:2)

首先,将该行拆分为元素:

product = str.split(/\|\|/)[2]

然后,尝试检查它是否包含“bar”和“soap”:

puts "match" if product =~ /bar/i and product =~ /soap/i
puts "match" if product =~ /bar.*soap|soap.*bar/i
puts "match" if product =~ /(?=.*bar)(?=.*soap)/i

[ADDED]

如果你想使用变量match_terms,试试这个:

re = match_terms.split(/,/).map { |t| "(?=.*#{Regexp::quote t})" }.join ""
puts "match" if product =~ /#{re}/i

terms = match_terms.upcase.split(/,/)
puts "match" if terms.select { |t| product.upcase.include? t }.size == terms.size

答案 1 :(得分:0)

示例数据看起来像您从数据库提取中看到的标准管道分隔('|')文件。通常会在输出中看到具有空值的字段显示为||

不是尝试使用正则表达式来解析它,而是通常通过拆分管道来处理,或者通过管道而不是逗号作为列分隔符将其视为CSV记录。如果您获得该字段实际上具有内容的记录,则拆分双管道(||)将失败。

这是两个不同的样本,显示我是如何做到的。第一个是将|拆分为字段。

text = '894975||0||Lever 2000 Anti-Bacterial Bar Soap ||Health & Spa/Personal Care/Body Care/Soap'
fields = text.split('|')
此时

fields看起来像:

[
    [0] "894975",
    [1] "",
    [2] "0",
    [3] "",
    [4] "Lever 2000 Anti-Bacterial Bar Soap ",
    [5] "",
    [6] "Health & Spa/Personal Care/Body Care/Soap"
]

抓住第五个字段检索产品:

product = fields[4]
=> "Lever 2000 Anti-Bacterial Bar Soap" 

第二种方法是将内容视为包含|分隔符的CSV文件:

require 'csv'

text = <<EOT
894975||0||Lever 2000 Anti-Bacterial Bar Soap ||Health & Spa/Personal Care/Body Care/Soap
EOT

CSV.parse(text, :col_sep => '|') do |row|
  puts row[4]
end

=> "Lever 2000 Anti-Bacterial Bar Soap" 

使用CSV执行此操作的优点是可以在文本中找到|字符,CSV将正确处理嵌入式管道的解码。

因为只有一个样本输入行,所以这个解决方案不能更彻底。