首先,我认为您的正则表达式需要一些修复。让我们看看你有什么:
test.com(\/\??index_.*.php\??(.*)|\/\?(.*)|\/|)+(\s)*(?!.)
第二种选择已经处理了您?在开头使用 optional 的情况:index...
test.com(\/index_.*.php\??(.*)|\/\?(.*)|\/|)+(\s)*(?!.)
现在你可能只希望第一个(.*)被允许,如果之前确实有一个文字?。否则你会匹配test.com/index_fb2.phpanystringhereandyouprobablydon'twantthat。所以移动相应的可选标记:
test.com(\/index_.*.php(\?(.*))?|\/\?(.*)|\/|)+(\s)*(?!.)
现在.*尽可能多地消耗任何角色。此外,.前面的php消耗任何字符。这意味着您将同时允许test.com/index_fb2php和test.com/index_fb2.html?someparam=php。让我们把它变成文字.并且只允许非问号字符:
test.com(\/index_[^?]*\.php(\?(.*))?|\/\?(.*)|\/|)+(\s)*(?!.)
现在第一个、第二个和第三个选项可以合并为一个,如果我们也将文件名设为可选:
test.com(\/(index_[^?]*\.php)?(\?(.*))?|)+(\s)*(?!.)
最后,+可以删除,因为(.*)内部已经可以处理所有可能的重复。也(something|)与(something)?:
test.com(\/(index_[^?]*\.php)?(\?(.*))?)?(\s)*(?!.)
看到您的输入示例,这似乎更接近您实际想要匹配的内容。
然后回答你的问题。什么(?!.)取决于您是否使用singleline模式。如果你这样做了,它就断言你已经到达了字符串的末尾。在这种情况下,您可以简单地将其替换为\Z,它始终匹配字符串的结尾。如果你不这样做,那么它断言你已经到了一行的末尾。在这种情况下,您可以使用$,但您还需要使用多行模式,以便也$匹配行尾。
因此,如果您使用singleline模式(这可能意味着每个字符串只有一个 URL),请使用以下命令:
test.com(\/(index_[^?]*\.php)?(\?(.*))?)?(\s)*\Z
如果您不使用singleline模式(这可能意味着您可以在自己的行中有多个 URL),您还应该使用multiline模式和这种锚点:
test.com(\/(index_[^?]*\.php)?(\?(.*))?)?(\s)*$