首页 > 解决方案 > 如何检测正则表达式是否可以用静态文本搜索替换?

问题描述

如何检测某个正则表达式字符串是否“简单”,即它可以用一个简单的字符串替换(并且完全避免使用正则表达式)。

例如:

input regex        simple text form (if possible)
--------------------------------------------------
foo\.bar     --->  foo.bar
foo          --->  foo
ba\[12\]r    --->  ba[12]r
ba.*foo      --->  (not possible to represent as plain string)

基本上,我正在寻找与此答案RegExp.escape中描述 的神话相反的a ,它要么与提到的相反,要么以某种方式报告无法进行转换。RegExp.unescapeRegExp.escape

正在寻找 JavaScript 解决方案,但 Java 也是可以接受的。

标签: javascriptjavaregex

解决方案


基本上,我正在寻找与此答案RegExp.escape中描述 的神话相反的a ,它要么与提到的相反,要么以某种方式报告无法进行转换。RegExp.unescapeRegExp.escape

此功能应处理大多数情况。如果无法进行转换,则返回undefined。它没有(但可以扩展到)做的是例如转换a{3}aaa或转换[a]a.

function cape(inre)
{
  if (/[iy]/.test(inre.flags)) return // these flags are not "simple"
  instr = inre.source
  outstr = ''
  special = '\\^$*+?.()|{}[]'
  // these so-called non-special characters after \ are not "simple":
  non_special = 'bBdDsSwW123456789'
  function pint(base, size)
  { // helper function for \0, \xhh and \uhhhh
    for (n = l = 0; l < size && !isNaN(d = parseInt(instr[i+1], base)); ++i, ++l)
      n = n*base+d
    return String.fromCharCode(n)
  }
  for (i = 0; c = instr[i]; outstr += c, ++i)
  { // convert input sequence to output text if possible
    if (c == '\\')
    {
      if (0 <= special.indexOf(c = instr[++i])) ; else
      if (0 <= non_special.indexOf(c)) return; else
      if (c == 'c') c = String.fromCharCode(instr.charCodeAt(++i)&31); else
      if (c == 'f') c = '\f'; else
      if (c == 'n') c = '\n'; else
      if (c == 'r') c = '\r'; else
      if (c == 't') c = '\t'; else
      if (c == 'v') c = '\v'; else
      if (c == '0') c = pint(8, 3); else
      if (c == 'x') c = pint(16, 2); else
      if (c == 'u') c = pint(16, 4)
    }
    else
      if (0 <= special.indexOf(c)) return
  }
  return outstr
}
console.log('input regex        simple text form (if possible)')
console.log('--------------------------------------------------')
testcases = [/foo\.bar/, /foo/, /ba\[12\]r/, /ba.*foo/]
for (i in testcases)
  s = testcases[i],
  console.log(s.source, ' '.repeat(11-s.source.length), '---> ', cape(s))


推荐阅读