JavaScript正则表达式以任何顺序匹配多个可选字符串

时间:2017-01-26 22:36:26

标签: javascript regex regex-lookarounds

我一直在努力解决这个问题并且无法理解。我在Regex to match string containing two names in any order中看到,可以使用外观来查找以任何顺序出现的单词。我在该帖子的示例中添加了一些其他组:

const regex = /^(?=.*\b(jack)\b)(?=.*\b(james)\b).*$/;
"hi james this is jack".match(regex);
  // => ["hi james this is jack", "jack", "james"]

但是,我也想让这两个词都是可选的。就是这样:

"hi james this is jack".match(someMagicRegex);
  // => ["hi james this is jack", "jack", "james"]

"hi this is jack".match(someMagicRegex);
  // => ["hi this is jack", "jack", undefined]

"hi james".match(someMagicRegex);
  // => ["hi james", undefined, "james"]

重要的是匹配保持正确的顺序。那就是jack匹配始终是匹配数组中的第二个元素。

我尝试在不同的地方添加?(包括新分组后),但我尝试过的任何内容都没有产生预期效果。

这样的事情可能吗?


更新:更具体地说,我将在一系列CSS媒体查询中使用此功能,并希望匹配可选的min-width: Xpxmax-width: Ypx表达式:

"only screen and (min-width: 500px) and (max-width: 599px)".match(someMagicRegex);
  // => ["...", "500", "599"]

"only screen and (min-width: 500px)".match(someMagicRegex);
  // => ["...", "500", undefined]

"(max-width: 599px)".match(someMagicRegex);
  // => ["...", undefined, "599"]

(其中第二个匹配将是最小宽度值的数字部分,第三个匹配将是最大宽度值的数字部分。)

4 个答案:

答案 0 :(得分:0)

更新这是一个有效的例子。我使用了2个regural表达式。首先在CSS文件/字符串中查找类或标记,第二个正则表达式是查找所需的属性。



var fileCSS='.entry-meta {position: relative; top: 5px; left: 5px; font-size: 0.8em; line-height: 18px; color: #aaa; } .entry-footer { display: inline; color: white; margin: 0 2em; padding: 0; font-size: 0.8em; line-height: 18px; } div { MIN-width: 200px; display: block; max-width: 80% ; position: relative; background: rgba(255,255,255,0.05); padding-bottom: 20px; } img { width: 640px; min-width: 12vh ;height: auto; max-width: 800px; margin-bottom: 10px; }';

var properties = ['min-width', 'max-width'];

function pMatch(CSS, classOrTag, propertiesToFind) {
	var foundProperties=[]; var found=null;
	mainREGEX= new RegExp(classOrTag+"\\s*[{][()#\"'/\*a-z0-9\\s:%;*,.=-]*[}]", 'i');
	var found=CSS.match(mainREGEX)[0];
	if(found!==null) {
		for(a=0; a<propertiesToFind.length; a++) {
			propertyREGEX=new RegExp('('+propertiesToFind[a]+'\\s?:\\s?[0-9.]+[a-z%\\s]+).?;', 'i');
			var property=found.match(propertyREGEX);
			property?foundProperties.push(property[1]):foundProperties.push('undefined');
		}
	}
	return foundProperties;
}
console.log(pMatch(fileCSS, 'div', properties));
console.log(pMatch(fileCSS, '.entry-meta', properties));
console.log(pMatch(fileCSS, 'img', properties));
&#13;
&#13;
&#13;

答案 1 :(得分:0)

不确定匹配数组(?)中的第一个结果是否需要完全匹配,但这可以给你一个想法。没有'魔法正则表达式'(至少来自我),只是普通的正则表达式array,带有捕获组:

regex = ["min-width:\\s*(\\d+)px","max-width:\\s*(\\d+)px"];

str = "only screen and (min-width: 500px) and (max-width: 599px)";

//str = "only screen and (min-width: 500px)"; 

//str="(max-width: 599px)";


matches = [];

for( i = 0; i < regex.length; i++ ) {
    if( RegExp(regex[i]).exec(str) ) {
        matches.push(RegExp(regex[i]).exec(str)[1]);
    } else {
        matches.push(undefined)
    }
}

console.log(matches);

测试案例2:

regex = ["min-width:\\s*(\\d+)px","max-width:\\s*(\\d+)px"];



str = "only screen and (min-width: 500px)"; 

//str="(max-width: 599px)";


matches = [];

for( i = 0; i < regex.length; i++ ) {
    if( RegExp(regex[i]).exec(str) ) {
        matches.push(RegExp(regex[i]).exec(str)[1]);
    } else {
        matches.push(undefined)
    }
}

console.log(matches);

测试案例3:

regex = ["min-width:\\s*(\\d+)px","max-width:\\s*(\\d+)px"];



str="(max-width: 599px)";


matches = [];

for( i=0; i < regex.length; i++ ) {
    if( RegExp(regex[i]).exec(str) ) {
        matches.push(RegExp(regex[i]).exec(str)[1]);
    } else {
        matches.push(undefined)
    }
}

console.log(matches);

答案 2 :(得分:0)

很抱歉,我的回答是在python中,但它应该在任何语言中使用相同的外观和反向引用。

以下代码正确匹配了所有三个测试用例,我希望它几乎可以在任何情况下正确匹配:

import re

strings = ["only screen and (min-width: 500px) and (max-width: 599px)", "only screen and (min-width: 500px)", "(max-width: 599px)"]

regex = re.compile(r'(min|max)-width:\s*(\d+)px(.*(?!\1)(max|min)-width:\s*(\d+)px)?')
for string in strings:
    match = re.search(regex, string)
    print
    print string
    if match:
        term_1 = match.group(1)
        value_1 = match.group(2)
        term_2 = match.group(4)
        value_2 = match.group(5)
        print "Match!\n{} {}".format(term_1+"-width:", value_1)
        if term_2:
            print "{} {}".format(term_2+"-width:", value_2)
    else:
        print "Not a match"

当我跑步时,我得到了这个输出:

only screen and (min-width: 500px) and (max-width: 599px)
Match!
min-width: 500
max-width: 599

only screen and (min-width: 500px)
Match!
min-width: 500

(max-width: 599px)
Match!
max-width: 599

Jason Cohen对this问题的回答解释了关键思想。他解释说,前瞻(或者在这种情况下是负向前瞻)意味着“匹配 expr 但在此之后继续匹配原始匹配点。”

在我的示例中,前瞻检查以确保它没有查看它在开头匹配的相同字符串,然后检查在同一点是否有max或{{1} }。请注意,在第一个min之后,甚至px都括在括号中。这使它不会太贪婪。此外,整个第二个术语都标有.*,以便字符串仍然匹配,即使找不到第二个匹配项。

答案 3 :(得分:0)

这里有另一个解决方案。它使用RegExp来匹配模式,使用while来存储值:

function getMatches (str) {
    var reg = /(min|max)-width\s*:\s*(\d*\.?\d+)/g,
        ret = [undefined, undefined],
        arr;
    while ((arr = reg.exec(str)) !== null) {
        ret[+(arr[1] === "max")] = arr[2];
    }
    return ret;
}

Jsfiddle示例:https://jsfiddle.net/elchininet/bwg1onk6/