使用正则表达式拆分Rubyon单词列表中的字符串
我试图根据停止词列表将Ruby中的字符串拆分为更小的子字符串或短语。当我直接定义正则表达式模式时,split方法起作用;但是,当我试图通过在split方法本身中求值来定义模式时,它不起作用 在实践中,我想读一个外部文件的停止词,并用它来分割我的句子。所以,我希望能够从外部文件构造模式,而不是直接指定它。我还注意到,当我使用“pp”和“puts”时,我会有非常不同的行为,我不知道为什么。我在Windows上使用Ruby 2.0和记事本+使用正则表达式拆分Rubyon单词列表中的字符串,ruby,regex,string,Ruby,Regex,String,我试图根据停止词列表将Ruby中的字符串拆分为更小的子字符串或短语。当我直接定义正则表达式模式时,split方法起作用;但是,当我试图通过在split方法本身中求值来定义模式时,它不起作用 在实践中,我想读一个外部文件的停止词,并用它来分割我的句子。所以,我希望能够从外部文件构造模式,而不是直接指定它。我还注意到,当我使用“pp”和“puts”时,我会有非常不同的行为,我不知道为什么。我在Windows上使用Ruby 2.0和记事本+ require 'pp' str = "The forc
require 'pp'
str = "The force be with you."
pp str.split(/(?:\bthe\b|\bwith\b)/i)
=> ["", " force be ", " you."]
pp str.split(/(?:\bthe\b|\bwith\b)/i).collect(&:strip).reject(&:empty?)
=> ["force be", "you."]
上面的最后一个数组是我想要的结果。但是,这在以下情况下不起作用:
require 'pp'
stop_array = ["the", "with"]
str = "The force be with you."
pattern = "(?:" + stop_array.map{|i| "\b#{i}\b" }.join("|") + ")"
puts pattern
=> (?thwit)
puts str.split(/#{pattern}/i)
=> The force be with you.
pp pattern
=> "(?:\bthe\b|\bwith\b)"
pp str.split(/#{pattern}/i)
=> ["The force be with you."]
更新:使用下面的注释,我修改了我的原始脚本。我还创建了一个分割字符串的方法
require 'pp'
class String
def splitstop(stopwords=[])
stopwords_regex = /\b(?:#{ Regexp.union(*stopwords).source })\b/i
return split(stopwords_regex).collect(&:strip).reject(&:empty?)
end
end
stop_array = ["the", "with", "over"]
pp "The force be with you.".splitstop stop_array
=> ["force be", "you."]
pp "The quick brown fox jumps over the lazy dog.".splitstop stop_array
=> ["quick brown fox jumps", "lazy dog."]
你必须掩盖反斜杠:
"\\b#{i}\\b"
i、 e
以及一个小的改进/简化:
pattern = "\\b(?:" + stop_array.join("|") + ")\\b"
然后:
如果您的停止列表很短,我认为这是正确的方法。我会这样做:
stop_array = ["the", "with"]
re = Regexp.union(stop_array.map{|w| /\s*\b#{Regexp.escape(w)}\b\s*/i})
"The force be with you.".split(re) # =>
[
"",
"force be",
"you."
]
str = "The force be with you."
stop_array = %w[the with]
stopwords_regex = /(?:#{ Regexp.union(stop_array).source })/i
str.split(stopwords_regex).map(&:strip) # => ["", "force be", "you."]
使用Regexp.union
时,务必注意生成的实际模式:
/(?:#{ Regexp.union(stop_array) })/i
=> /(?:(?-mix:the|with))/i
嵌入的(?-mix:
关闭模式内不区分大小写的标志,这可能会破坏模式,导致它获取错误的内容。相反,您必须告诉引擎仅返回模式,而不返回标志:
/(?:#{ Regexp.union(stop_array).source })/i
=> /(?:the|with)/i
这就是为什么pattern=“(?:\b\b | \b与\b)”
不起作用的原因:
/#{pattern}/i # => /(?:\x08the\x08|\x08with\x08)/i
Ruby将“\b”
视为退格字符。请改用:
pattern = "(?:\\bthe\\b|\\bwith\\b)"
/#{pattern}/i # => /(?:\bthe\b|\bwith\b)/i
s=“原力与你同在。”
停止单词=%w |带的是|
#动态创建不区分大小写的regexp
regexp=regexp.new stop_words.join(“|”),true
结果=[]
while(match=regexp.match)
word=match.pre_match,除非match.pre_match.empty?
结果/(?:\b\b | \b with\b)/
写得更好/\b(?:the | with)\b/
。使用生成的模式,说明这将如何解决OP的问题。
/#{pattern}/i # => /(?:\x08the\x08|\x08with\x08)/i
pattern = "(?:\\bthe\\b|\\bwith\\b)"
/#{pattern}/i # => /(?:\bthe\b|\bwith\b)/i
s = "the force be with you."
stop_words = %w|the with is|
# dynamically create a case-insensitive regexp
regexp = Regexp.new stop_words.join('|'), true
result = []
while(match = regexp.match(s))
word = match.pre_match unless match.pre_match.empty?
result << word
s = match.post_match
end
# the last unmatched content, if any
result << s
result.compact!.map(&:strip!)
pp result
=> ["force be", "you."]