我有一个像这样的输入字符串:
如果你{已经计划|希望} {转到} {露营|户外活动 休息|钓鱼|狩猎},你{可能喜欢|需要|只需要|可能会使用}睡觉 包[产品名称]。 {It |这个睡袋} {意图是理想的} [SEASON]和[TYPE] {type | form-factor}设计| sewed | made。
现在,我需要做这件事:
所以,输出字符串就像这样:
如果你想去钓鱼,你可能会喜欢睡觉 袋耐磨山。这款睡袋非常适合 冬季,由茧形状设计。
我知道如何解决#1问题,但对问题#2有所了解。 此外,可以有嵌套的方括号,例如:{some word | {some word2 | {some word3 | some word5}} | some word4}。
所以我需要一个Ruby的正则表达式,或者可能是解决这个问题的另一种方法。
答案 0 :(得分:1)
假设这是我们的文字:
text =
'如果你{决定|计划|希望} {去[露营|户外休息|钓鱼|狩猎},你{可能需要|只需要|可能会使用}睡袋[产品名称]。 {It |这个睡袋} {对于[SEASON]来说是理想的}和{TYPE] {type | form-factor}设计| sewed | made}。 {这是| {真的| {不是那么}}}} |当然}一个很棒的包。'
注意我在最后一句中添加了一些嵌套大括号。
首先,获取散列指定的替换:
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)
返回:
"如果你{已经计划|希望} {去{露营|户外休息|钓鱼|狩猎},你{可能需要|只需要|可能会使用}睡袋坚硬的山。 {It |这个睡袋} {对于秋季来说是理想的}并且由低薪工人{type | form-factor} {设计|制造}。 {这是| {真的| {不是那么}}}} |当然}一个很棒的包。"
如果s = [...]
有一个键h[s]
,则每个字符串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
返回:
"如果你决定去钓鱼,你需要睡袋Hard Wear Mountain。这款睡袋适合秋季使用,并由薪水过低的工人缝制。这是一个很棒的包。"
这里的想法是做一系列替换,每次'{...|...|... }'
形式的字符串...
不包含左括号,因此不包含嵌套块。为了显示这些步骤,下面显示了顺序随机替换(当然可能与我上面的不同)。
第一轮替换
str # as above
old = str
new = old.gsub(/\{[^{]+?(?:\|[^{}]+?)+\}/) do |s|
a = s[1..-2].split('|')
a[rand(a.size)]
end
new==old #=> false
现在new
等于:
"如果你计划打猎,你只需要睡袋Hard Wear Mountain。它是秋季的理想选择,由薪酬过低的工人制造。 {这是| {真的|所有}} |当然}一个伟大的包。"
请注意,所有非嵌套的大括号块都已解析,嵌套块:
{It is|{really|{not so|all that}}|certainly}
嵌套级别的减少了一个:
{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
现在等于:
"如果你计划打猎,你只需要睡袋Hard Wear Mountain。它是秋季的理想选择,由薪酬过低的工人制造。 {这绝对是一个很棒的包。"
第三轮替换
old=new
new = old.gsub(/\{[^{]+?(?:\|[^{}]+?)+\}/) do |s|
a = s[1..-2].split('|')
a[rand(a.size)]
end
new==old #=> false
new
现在等于:
"如果你计划打猎,你只需要睡袋Hard Wear Mountain。它是秋季的理想选择,由薪酬过低的工人制造。当然是一个很棒的包。"
我们现在已经完成了,但在我们再次尝试找到new == old #=> true
之前不会知道。
第四轮替换
old=new
new = old.gsub(/\{[^{]+?(?:\|[^{}]+?)+\}/) do |s|
a = s[1..-2].split('|')
a[rand(a.size)]
end
new==old #=> true
答案 1 :(得分:0)
The following regex will capture the text, also for nested cases:
(?<=[|{])([\w\s]+?)(?=[}|])
You can then determine the number of matches and choose a random index less than the match group size.