解析和转换文章以进行文章复制

时间:2015-04-23 04:30:40

标签: ruby regex

我有一个像这样的输入字符串:

  

如果你{已经计划|希望} {转到} {露营|户外活动   休息|钓鱼|狩猎},你{可能喜欢|需要|只需要|可能会使用}睡觉   包[产品名称]。 {It |这个睡袋} {意图是理想的}   [SEASON]和[TYPE] {type | form-factor}设计| sewed | made。

现在,我需要做这件事:

  1. 将值放入方括号(例如[PRODUCT NAME])变为Hard Wear 山)
  2. 从花括号中取一个随机单词并粘贴它(例如     {determin | planned | wish}计划好了}
  3. 所以,输出字符串就像这样:

      

    如果你想去钓鱼,你可能会喜欢睡觉   袋耐磨山。这款睡袋非常适合   冬季,由茧形状设计。

    我知道如何解决#1问题,但对问题#2有所了解。 此外,可以有嵌套的方括号,例如:{some word | {some word2 | {some word3 | some word5}} | some word4}。

    所以我需要一个Ruby的正则表达式,或者可能是解决这个问题的另一种方法。

2 个答案:

答案 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.