我有这样的正则表达式匹配字符串文字:
/"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'/
如何测试给定的字符串是否包含无效(未闭合的字符串),如下所示:
echo "asd \\\"asd && rm
它应匹配:
echo "foo
echo "asd \\\"asd && rm
echo "asd \" " asd && rm " \"
但不是:
echo "asd \\\"asd" && rm
echo "asd \"asd" && rm
echo "asd \\\\\"asd" && echo " \" " && rm
如何使用javascript(没有特定的PCRE扩展名)创建此类正则表达式解决方案是首选。
编辑:我已经使用php解决了这个问题:
/(?:"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*')(*SKIP)(*F)|"/
是否可以在javascript中执行相同的操作,还是需要解析字符串?
答案 0 :(得分:2)
你的php模式实际上是错误的,因为它不适用于单引号。如果您使用"
更改上一个["']
,则可以轻松更正此问题。请注意,您也不需要使用变通方法[\s\S]
,因为pcre具有单行修饰符s:
/(?:"[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*')(*SKIP)(*F)|["']/s
然而,如果使用(*SKIP)(*FAIL)
组合似乎引诱,它以低效的模式设计结束:以交替开始的非锚定模式。结果,对于不是引用的每个字符(在引用部分之外),交替的三个分支都没有被测试。
这就是为什么我建议一种更有效的方法,从一开始就检查字符串(锚定模式)并使用占有量词:
$p = '~(?: [^"\']+
| " [^"\\\\]* (?: \\\\. [^"\\\\]* )* "
| \' [^\'\\\\]* (?: \\\\. [^\'\\\\]* )* \'
)*+ # possessive quantifier
. # a character that can only be a quote (single or double)
~xAs'; // modifiers: extended, Anchored, singleline
var_dump(preg_match($p, $str));
由于量词是贪婪的(它需要一切可能)和占有(它禁止正则表达式引擎回溯),因此点匹配的字符只能是孤立引用(如果存在)(否则,模式失败)。
与javascript相同的想法,除了你必须使用前瞻的原子性质来模拟占有量词:(?=(...))\1
var p = /^(?=((?:[^"']+|"[^"\\]*(?:\\[^][^"\\]*)*"|'[^'\\]*(?:\\[^][^'\\]*)*')*))\1./;
console.log(p.test(s));
您还可以构建状态机:
String.prototype.unbalancedQuotes = function () {
var p = /[\\"']/g, state = {
e: false, // escape state: index of the last quoted escape character or false
q: undefined, // quote state: last opening quote or undefined
update: function(m) {
if ( this.e === m.index - 1 ) { // when the current character is escaped:
this.e = false; //set the escaped state to false
} else { // otherwise:
if ( this.q && m[0] == '\\' ) // if the character is a quoted backslash
this.e = m.index; // store the current index
else // else change eventually the quote state
this.q = this.q == m[0] ? undefined : this.q || m[0];
}
}
};
while ( (m = p.exec(this)) !== null ) state.update(m);
return Boolean(state.q);
};
var s = '"a\\h"bcd';
console.log(s);
console.log(s.unbalancedQuotes());
答案 1 :(得分:1)
在php中,我使用正则表达式解决了这个问题:
/(?:"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*')(*SKIP)(*F)|"/
在javascript中我创建了解析函数:
function unclosed_strings(string) {
if (!string.match(/["']/)) {
return false;
}
var count = 0;
string.match(/\\*["']/g).forEach(function(quote) {
var slashes = quote.match(/\\/g);
if (slashes && slashes.length % 2 === 0 || !slashes) {
count++;
}
});
return count % 2 !== 0;
}