除非以某个字符开头和结尾,否则匹配字符串。

4
我正在尝试使用JavaScript中的正则表达式来决定是否删除消息。我希望如果消息包含 "string"(无论出现在哪里),除非被冒号包围,否则就将其删除。
  • string - 将被删除
  • blah string - 将被删除
  • :string blah - 将被删除
  • :string: string - 将被删除
  • thing :string: - 不会被删除
我正在使用JavaScript,目前我正在使用 message.match(/string/i) 来查看是否应该删除该消息。我已经尝试过负向先行断言,但可能用错了。
编辑:抱歉没有早些说明。 :blahstring::stringblah:以及:blahstringblah:也不应被删除。

@guest271314 因为单词 string 被冒号包围 - Asons
@Sparky 已删除 - Kognise
@LGSon,“:string: string - gets deleted”和“thing :string: - doesn't get deleted”有什么区别?为什么第二种情况中的“:string:”没有匹配到? - guest271314
关于您的编辑: “bla”是要字面理解,还是可以是任何字母序列?它可以包括空格和标点符号吗?现在并不是非常清楚... - trincot
但是对于任意序列,只要字符串以冒号开头和结尾就足以使其可接受,例如“:这是一个带有字符串的长句子,应该没问题:”。这样的字符串应该被删除吗? - trincot
显示剩余6条评论
5个回答

4

有一些边界情况,其中冒号只出现在"string"的一侧。因此,我认为更容易的方法是删除所有":string:"的出现,然后再查找"string"的匹配:

function deleteIt(msg) {
    return /string/i.test(msg.replace(/:\w*string\w*(?=:)/ig, ":"));
}

console.log(deleteIt("this is :string ")); // true
console.log(deleteIt("this is string: ")); // true
console.log(deleteIt("string:string: ")); // true
console.log(deleteIt("this is :string: ")); // false
console.log(deleteIt("this is :blastring:stringbla:string: ")); // false

上述代码片段中的最后一个测试是一个特殊情况。冒号被前面和后面的“字符串”共享。根据您是否希望忽略这些“字符串”出现,您可能需要用第二个冒号的普通捕获替换前瞻。
补充说明:在你编辑问题的时候,你说“:blastring:”或“:stringbla:”也不应该触发删除。
因此,我在上面的正则表达式中两次添加了“\w*”,以符合这个额外要求。
如果也可以允许标点符号或其他非字母字符出现在冒号和“字符串”之间,例如“:,-°string^0&:”,只要不出现空格,则使用“\S*”而不是“\w*”。

我看到你对问题的编辑,所以我在正则表达式中添加了两个\w*以符合额外的要求。如果这是你需要的,请告诉我。如果你想检测字面上的"bla",请用(bla)?替换这些\w* - trincot

4
如果支持后顾,您可以使用:
/(?<!:(?=string:))string/i

查看正则表达式演示

详情

  • (?<!:(?=string:)) - 负向先行断言,如果当前位置左侧紧挨着的是:且不是紧接着string:则匹配失败。
  • string - 一个字符串

var strs = ['string - gets deleted','blah string - gets deleted',':string blah - gets deleted',':string: string - gets deleted','thing :string: - doesnt get deleted'];
var rx = /(?<!:(?=string:))string/i;
for (var s of strs) {
  console.log(s, "=>", rx.test(s));
}

输出:

string - gets deleted => true
blah string - gets deleted => true
:string blah - gets deleted => true
:string: string - gets deleted => true
thing :string: - doesnt get deleted => false

没有后顾之忧的版本

它基于一个正则表达式,可以匹配既没有冒号,又有两侧都有冒号的字符串。如果匹配中至少包含一个开头没有冒号的匹配项,则必须删除该条目。

var strs = ['string - gets deleted','blah string - gets deleted',':string blah - gets deleted',':string: string - gets deleted','thing :string: - doesnt get deleted'];
var rx = /(?::(?=string:))?string/gi;
for (var s of strs) {
  var matches = s.match(rx);
  console.log(s, "=>", (matches.some(function (x) { return !/^:/.test(x); }) ));
}


我猜我不小心点击了编辑而不是我的答案,看到这个的人请忽略我的编辑。 - Adam H
啊,我很困惑地看到我的答案中另一个正则表达式 :) - Wiktor Stribiżew
@UnknownUser,是的,请查看演示。只有最后一个是“false”。 - Wiktor Stribiżew
@UnknownUser 它不能通过哪个测试用例?请将其添加到您的问题中。 - blhsing
@UnknownUser 添加了一个没有lookbehind的版本。 - Wiktor Stribiżew
显示剩余4条评论

1
这是在我的测试中有效的内容: ^.*(?<!\:)string(?!\:).*$
  • ^ 匹配字符串的开头
  • .* 匹配任何字符任意次数
  • (?<!\:) 如果缺少:后缀,则匹配
  • string 匹配单词string
  • (?!\:) 如果缺少后缀,则匹配
  • .* 匹配任何字符任意次数
  • $ 匹配行尾

我喜欢这个解释,它真的帮助我澄清了一些问题,但是@blhsing的答案才是解决我的问题的那一个。 - Kognise
@UnknownUser,如果他的回答解决了问题,请将其标记为答案,以帮助未来的人们。 - Adam H
我认为这会给出":string"和"string:"错误的结果。 - trincot
@AdamH 我本来想帮忙的,但现在stackoverflow要让你等一会儿。 - Kognise

1

0

尝试

let s=[ "string",
        "blah string",
        ":string blah",
        ":string: string",
        "thing :string:",
        ":blahstring:",
        ":stringblah:",
        ":blahstringblah:",
      ];

let d=s.filter(x=> !x.match(/:.*string.*:/i) || x.match(/:.*string.*:.*string.*/i) || x.match(/.*string.*:.*string.*:/i));

console.log('Delete :', d);
console.log('Save   :', s.filter(x=>!d.includes(x)) );

我们将元素 d 放入“删除列表”中,该元素满足以下条件:

  • !x.match(/:string:/i) - 不包含 :string:
  • x.match(/:.*string.*:.*string.*/i) 包含 :string: 且后面的 string 没有被 : 包围
  • x.match(/.*string.*:.*string.*:/i) 与上述相同但反过来

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接