在字符串中查找字符,但更喜欢具有NFA的连续字符而不使用原子分组

时间:2013-09-16 14:41:28

标签: javascript regex

我正在尝试创建一个在字符串中的任何位置查找字符的正则表达式。我宁愿他们会先找到连续的字符。

让我举个例子,假设s = 'this is a test test string'并且我正在搜索 tst 我想找到它:

// Correct
//   v           vv
s = 'this is a test test string'

而不是:

// Incorrect
//   v  v         v
s = 'this is a test test string'

如果s = 'this is a test test tst string'

// Correct
//                       vvv
s = 'this is a test test tst string'

有几点需要注意:

  • 搜索字符是用户提供的(在这种情况下为tst
  • 我正在使用javascript,所以我不能支持atomi分组,我怀疑这会让这很容易

我最好的尝试是这样的:

var find = 'tst';
var rStarts = [];
var rEnds = [];
for (var i = 0; i < find.length - 1; i++) {
    rStarts.push(= '(' + find[i] + find[i + 1]  )
    rEnds.push( find[i] + '[^]*?' + find[i + 1] + ')' );
}

但是一半时间我意识到我不知道我在哪里。 任何想法如何做到这一点?

4 个答案:

答案 0 :(得分:1)

好吧,我仍然不确定你到底在寻找什么,但也许这样做会第一次尝试:

.*?(t)(s)(t)|.*?(t)(s).*?(t)|.*?(t).*?(s)(t)|(t).*?(s).*?(t)

regex101 demo

我在这里捕捉每一封信,但如果你不介意将它们分组......

.*?(tst)|.*?(ts).*?(t)|.*?(t).*?(st)|(t).*?(s).*?(t)

这将与您在问题中提到的部分相匹配。

答案 1 :(得分:1)

您可以这样做:

按照您喜欢的顺序计算针的所有子串组合的正则表达式,并按顺序匹配它们。因此,对于您的测试,您可以进行以下匹配:

/(tst)/
/(ts).*(t)/
/(t).*(st)/  // <- this one matches
/(t).*(s).*(t)/

计算正则表达式很棘手并且按正确顺序排列它们取决于你是否更喜欢4-1-1分割而不是2-2-2分割。

答案 2 :(得分:1)

这会找到一组提供的字母的最短集合:

function findChars(chars,string)
{
    var rx = new RegExp(chars.split("").join(".*?"),"g");
    var finds = [];
    while(res = rx.exec(string))
    {
        finds.push(res[0]);
        rx.lastIndex -= res[0].length-1;
    }
    finds.sort(function(a,b) { return a.length-b.length; })
    return finds[0];
}
var s2 = 'this is a test test tst string';
console.log(findChars('tst',s2));//"tst"
console.log(findChars('ess',s2));//"est ts"

答案 3 :(得分:0)

您可以使用前瞻模仿原子组,如this article中所述。这个正则表达式似乎做了想要的事情:

/^(?:(?=(.*?tst))\1|(?=(.*?ts.+?t))\2|(?=(.*?t.+?st))\3|(?=(.*?t.+?s.+?t))\4)/

......或以人类可读的形式:

^
(?:
   (?=(.*?tst))\1
   |
   (?=(.*?ts.+?t))\2
   |
   (?=(.*?t.+?st))\3
   |
   (?=(.*?t.+?s.+?t))\4
)

ref