我正在尝试通过以特定字符结尾的前缀来匹配字符串。例如,如果我的字符串是"abcd"
并以#
结尾,则任何以"abcd"
为前缀的单词都应匹配,只要它以#
结尾即可。这里有一些例子来帮助说明这种模式:
输入:"ab#"
给出true
(因为"ab"
是"abcd"
的前缀并以#
结尾)。
输入:"abcd#"
给出true
(因为"abcd"
是"abcd"
的前缀并以#
结尾)。
输入:"bc#"
给出false
(因为"bc"
不是"abcd"
的prefix。)
Input:"ab@"
给出false
("ab"
是"abcd"
的prefix,但不以#
结尾)。
输入:"ac#"
给出false
(虽然"ac"
包含在"abcd"
中,但它并不以"abcd"
的前缀开头)。
到目前为止,我已经设法提出了下面的表达式,该表达式似乎运行良好:
/(abcd|abc|ab|a)#/
虽然这是可行的,但不是很实用,因为较大的单词n
会使表达式变得很大:
/(n|n-1|n-2| ... |1)#/
是否有方法可以重写此表达式,使其更具伸缩性和简洁性?
我的尝试示例(使用JS):
const regex = /(abcd|abc|ab|a)#/;
console.log(regex.test("abcd#")); // true
console.log(regex.test("ab#")); // true
console.log(regex.test("abc#")); // true
console.log(regex.test("abz#")); // false
console.log(regex.test("abc@")); // false
Edit:提供的某些解决方案很好,可以满足我的要求,但是,对于这个特定问题,我正在寻求使用纯正则表达式来匹配前缀的解决方案。
仅在此处使用String#startsWith
和String#endsWith
:
String input = "abcd";
String prefix = "ab#";
if (input.startsWith(prefix.replaceAll("#$", "")) && prefix.endsWith("#")) {
System.out.println("MATCH");
}
else {
System.out.println("NO MATCH");
}
Edit:上面的JavaScript版本:
var input = "abcd";
var prefix = "ab#";
if (input.startsWith(prefix.replace(/#$/, "")) && prefix.endsWith("#")) {
console.log("MATCH");
}
else {
console.log("NO MATCH");
}
这是一个左侧字段JavaScript选项。构建和构建有效前缀的数组,在该数组上使用join来创建您的正则表达式模式。
var validPrefixes = ["abcd",
"abc",
"ab",
"a",
"areallylongprefix"];
var regexp = new RegExp("^(" + validPrefixes.join("|") + ")#$");
console.log(regexp.test("abcd#"));// true
console.log(regexp.test("ab#")); // true
console.log(regexp.test("abc#")); // true
console.log(regexp.test("abz#")); // false
console.log(regexp.test("abc@")); // false
console.log(regexp.test("areallylongprefix#")); //true
这可以适应旅行选择的语言,如果您的前缀是从数据库或类似的数据库中动态检索出来的,也很方便。
这是我的C#尝试:
private static bool test(string v)
{
var pattern = "abcd#";
//No error handling
return v.EndsWith(pattern[pattern.Length-1])
&& pattern.Replace("#", "").StartsWith(v.Replace("#",""));
}
Console.WriteLine(test("abcd#")); // true
Console.WriteLine(test("ab#")); // true
Console.WriteLine(test("abc#")); // true
Console.WriteLine(test("abz#")); // false
Console.WriteLine(test("abc@")); // false
Console.WriteLine(test("abc")); //false
/a(b(cd?)?)?#/
或者对于更长的例子,匹配前缀“ abcdefg#”:
/a(b(c(d(e(fg?)?)?)?)?)?#/
生成此正则表达式并不完全是琐碎的,但是有些选择是:
function createPrefixRegex(s) {
// This method creates an unnecessary set of parentheses
// around the last letter, but that won't harm anything.
return new RegExp(s.slice(0,-1).split('').join('(') + ')?'.repeat(s.length - 2) + '#');
}
function createPrefixRegex2(s) {
var r = s[0];
for (var i = 1; i < s.length - 2; ++i) {
r += '(' + s[i];
}
r += s[s.length - 2] + '?' + ')?'.repeat(s.length - 3) + '#';
return new RegExp(r);
}
function createPrefixRegex3(s) {
var recurse = function(i) {
if (i >= s.length - 1) {
return '';
}
if (i === s.length - 2) {
return s[i] + '?';
}
return '(' + s[i] + recurse(i + 1) + ')?';
}
return new RegExp(s[0] + recurse(1) + '#');
}
如果输入字符串在'#'字符之前没有前缀,并且它们假定字符串中的最后一个字符为'#',则这些命令可能会失败。