我有一个这样的输入字符串:
如果你{决定|计划|愿望} {去|去}到{露营|有户外 休息|钓鱼|打猎},你{可能喜欢|需要|只是需要|可以使用}睡觉 袋 [产品名称]。{它|这个睡袋}{是打算|是理想的} [SEASON] 和 {designed|sewed|made} by [TYPE] {type|form-factor}。
现在,我需要做这些事情:
- 将值放入方括号中(例如,[产品名称] 变为硬磨损 山)
- 从大括号中随机取出一个单词并粘贴它(例如。 {已决定|计划|愿望} 成为计划}
因此,输出字符串将如下所示:
如果你想去钓鱼,你可能喜欢睡觉 包硬穿山。这款睡袋非常适合 冬季,由茧外形设计。
我知道如何解决#1问题,但对问题#2有想法。 此外,还可以有嵌套的方括号,例如:{某些单词|{一些词2|{一些单词3|一些单词5}}|一些单词4}。
所以我需要一个 Ruby 的正则表达式,或者另一种方法来解决这个问题。
假设这是我们的文本:
text =
'如果你{决定|计划|愿望}{去|去}{露营|户外休息|钓鱼|狩猎},你{可能喜欢|需要|只需要|可以使用}睡袋[产品名称]。{它|这个睡袋} {是打算|是理想的} [季节] 和 {设计|缝制|制造} 由 [类型] {类型|外形}.{它是|{真的|{不是这样|所有这些}}|当然}是一个很棒的袋子。
请注意,我在最后一句中添加了一些嵌套的大括号。
首先,获取由哈希指定的替换:
h = { '[PRODUCT NAME]'=>'Hard Wear Mountain',
'[SEASON]'=>'fall',
'[TYPE]'=>'underpaid workers' }
如下:
r = /
[ # match a left bracket
.+? # match >= 1 characters non-greedily (stop at 1st right bracket)
] # match right bracket
/x
str = text.gsub(r,h)
返回:
"如果你{决定|计划|愿望}{去|去}{露营|户外休息|钓鱼|狩猎},你{可能喜欢|需要|只需要|可能使用}睡袋硬穿山。{它|这个睡袋}{是打算|是理想的}秋天和{设计|缝制|制造}由低薪工人{类型|外形}。{它是|{真的|{不是这样|所有这些}}|当然}是一个很棒的袋子。
如果每个字符串s = [...]
都有一个键s
,则h
被h[s]
替换;否则不进行替换。
现在进行更换,从内部{...|...|...}
开始,然后向外工作,直到不再进行更换:
old = str
loop do
new = old.gsub(/{[^{]+?(?:|[^{}]+?)+}/) do |s|
a = s[1..-2].split('|')
a[rand(a.size)]
end
break if new==old
old=new
end
old
返回:
"如果你决定去钓鱼,你需要睡袋硬穿山。这款睡袋专为秋季使用,由低薪工人缝制。这是一个很棒的袋子。
这里的想法是做一系列替换,每次字符串的形式'{...|...|... }'
其中...
不包含左括号,因此不包含嵌套块。为了显示这些步骤,下面显示了顺序随机替换(当然可能与我上面所说的不同)。
第一轮替换
str # as above
old = str
new = old.gsub(/{[^{]+?(?:|[^{}]+?)+}/) do |s|
a = s[1..-2].split('|')
a[rand(a.size)]
end
new==old #=> false
现在new
等于:
"如果你打算去打猎,你只需要睡袋硬穿山。它是秋季的理想选择,由低薪工人类型制造。{它是|{真的|所有这些}|当然}是一个很棒的包。
请注意,所有非嵌套大括号块都已解析,并且嵌套块:
{It is|{really|{not so|all that}}|certainly}
嵌套级别降低了 1:
{It is|{really|all that}|certainly}
由于{not so|all that}
已被all that
.此块中的随机替换按如下方式完成:
s0 = '{not so|all that}'
s1 = s0[1..-2]
#=> "not so|all that"
a = s1.split('|')
#=> ["not so", "all that"]
a[rand(a.size)]
#=> a[rand(2)] => a[1] => "all that"
第二轮替换
old=new
new = old.gsub(/{[^{]+?(?:|[^{}]+?)+}/) do |s|
a = s[1..-2].split('|')
a[rand(a.size)]
end
new==old #=> false
new
现在等于:
"如果你打算去打猎,你只需要睡袋硬穿山。它是秋季的理想选择,由低薪工人类型制造。{这是|所有|当然}一个伟大的袋子。
第三轮替换
old=new
new = old.gsub(/{[^{]+?(?:|[^{}]+?)+}/) do |s|
a = s[1..-2].split('|')
a[rand(a.size)]
end
new==old #=> false
new
现在等于:
"如果你打算去打猎,你只需要睡袋硬穿山。它是秋季的理想选择,由低薪工人类型制造。当然是一个很棒的包。
我们现在已经完成了,但直到我们再次尝试并找到那个new == old #=> true
才会知道。
第四轮替换
old=new
new = old.gsub(/{[^{]+?(?:|[^{}]+?)+}/) do |s|
a = s[1..-2].split('|')
a[rand(a.size)]
end
new==old #=> true
以下正则表达式将捕获文本,也适用于嵌套情况:
(?<=[|{])([ws]+?)(?=[}|])
然后,您可以确定匹配项的数量,并选择小于匹配组大小的随机索引。