尝试使用多行正则表达式重新定位单词

时间:2016-11-19 01:03:21

标签: ruby

我正在尝试使用结构定义来更改文件,如:

“typedef struct PET_fun1 {...}”有这样的定义:

“typedef struct {...} PET_fun1;”

  str = <<END
  typedef struct PET_fun1 { 
     char tam[1];
     char tma[2];
     char mta[2];
  }

  typedef struct PET_fun2 { 
     def : abc[3]
     def : bac[3]
     def : acb[3]
  }

  typedef struct PET_fun3 { 
     abc
  }

  typedef struct PET_fun4 { 
     ...
  }
  END

  puts str.gsub(/(typedef\s+struct\s+)(PET_\w+) ({.*})/m, '\1\3\2') # This regular expression isn't working.

成功进行字符串转换后我想要的输出如下所示:

  typedef struct { 
     char tam[1];
     char tma[2];
     char mta[2];
  } PET_fun1;

  typedef struct { 
     def : abc[3]
     def : bac[3]
     def : acb[3]
  } PET_fun2;

  typedef struct { 
     abc
  } PET_fun3;

  typedef struct { 
     ...
  } PET_fun4;

2 个答案:

答案 0 :(得分:2)

您的.*元素是贪婪的,它从第1行的字符串中的第一个{到第1行的字符串中的最后一个}一直匹配最后一行。您需要使用lazy quantifier,以便正则表达式在它找到的第一个}处停止。

您也可能希望PET_带上它的前置空格。

你的最终正则表达式应该是这样的:

str.gsub(/(typedef\s+struct\s*)( PET_\w+)( {.*?})/m, '\1\3\2')

答案 1 :(得分:1)

这个答案允许在每个&#34; typedef块&#34;中使用嵌套大括号。我们的想法是将字符串拆分为分隔&#34; typedef块&#34;的空白行,操纵包含每个块的字符串,然后将它们连接回一个字符串,每个相邻对之间有一个空行。通过这种方式,在每个块中,我们可以贪婪地搜索右括号('}'),从而允许嵌套括号。

<强>代码

R = /
    (?<=typedef\sstruct) # match 'typedef struct' in a positive lookbehind
    (\s+\w+)             # match > 0 spaces followed by a word in capture group 1
    (\s+{.+})            # match > 0 spaces, then '{', then any number of any
                         # character, greedily, then '}' in capture group 2
    /xm                  # free-spacing regex definition and multiline modes

def doit(str)
  str.split("\n\n").map { |s| s.sub(R, '\2\1') }.join("\n\n")
end

示例

str = <<END
  typedef struct PET_fun1 { 
     char tam[1];
     { char { tma}[2];} 
     char mta[2];
  }

  typedef struct PET_fun2 { 
     def : abc[3]
     def : bac[3]
     def : acb[3]
  }

  typedef struct PET_fun3 { 
     abc
  }

  typedef struct PET_fun4 { 
     ...
  }
END

现在使用此字符串执行doit

puts doit(str)
  #  typedef struct { 
  #     char tam[1];
  #     { char { tma}[2];} 
  #     char mta[2];
  #  } PET_fun1
  #
  #  typedef struct { 
  #     def : abc[3]
  #     def : bac[3]
  #     def : acb[3]
  #  } PET_fun2
  #
  #  typedef struct { 
  #     abc
  #  } PET_fun3
  #
  #  typedef struct { 
  #     ...
  #  } PET_fun4

<强>解释

这三个步骤如下。

a = str.split("\n\n")
  #=> ["  typedef struct PET_fun1 { \n     char tam[1];\n     { char { tma}[2];} \n     char mta[2];\n  }",
  #    "  typedef struct PET_fun2 { \n     def : abc[3]\n     def : bac[3]\n     def : acb[3]\n  }",
  # "  typedef struct PET_fun3 { \n     abc\n  }", "  typedef struct PET_fun4 { \n     ...\n  }\n"]

接下来,

b = a.map { |s| s.sub(R, '\2\1') }
  #=> ["  typedef struct { \n     char tam[1];\n     { char { tma}[2];} \n     char mta[2];\n  } PET_fun1",
  #    "  typedef struct { \n     def : abc[3]\n     def : bac[3]\n     def : acb[3]\n  } PET_fun2",
  #    "  typedef struct { \n     abc\n  } PET_fun3", "  typedef struct { \n     ...\n  } PET_fun4\n"] 

最后,

b.join("\n\n")

给我们示例中返回的字符串。