如何排除正则表达式模式字符类中的最后一个字符


how to exclude a character in a regex pattern character class if last character?

如果这个问题措辞不好(或者已经问过了。我真的试着找到了),很抱歉。

如果字符类中的一个特定字符恰好是最后一个字符(尽管它仍然可以保留在其他位置),是否可以将其从匹配中排除?我正在处理的类似于在较大的字符串中查找url,并且需要在模式中包括句点,但如果最后一个字符是句点,则将其排除在句末。

那么,在一个模式(其他url内容)"(/[a-zA-Z0-9._-]*)?"中,是否有方法只排除最后一个句点(如果存在)?请注意,上面将特别是域后的uri段,但我只想匹配

"/some_uri/segments.php"

在两个中

"www.domain.com/some_uri/segments.php" 

"www.domain.com/some_uri/segments.php."

同时允许在uri中存在多个周期。

如果以上内容不清楚,想象一下我正在寻求一种方法来排除一个单词中的最后一个字母,当且仅当它是"z"。因此,"dozzer"answers"dozzerz"在句子结构中都匹配为"dozzr"(因此……与字符串末尾的位置不匹配)。我玩过lookahead之类的游戏,但还没有找到方法。我想知道这是否不可能(在一个正则表达式中)。

谢谢你抽出时间!

编辑

我很抱歉没有让它变得更清楚,但我需要在一块文本内进行匹配。我正在做的是浏览文本,找到所有的网址,并对它们应用标记。因此,我不能使用位置运算符,例如$来匹配字符串的末尾。这是最大的问题。

除非其他人在这之后发布一个有效的答案,否则我想我将不得不同意M477h3w1012,并得出结论,它不能单独在正则表达式中完成。在找到匹配项后,我需要进行条件检查,以确定它们是否有拖尾期。但是,再次非常感谢大家的时间和帮助


我认为这不可能在一个正则表达式检查中。。。也许有人能纠正我的错误,但我现在不这么认为(或者我现在无法优化事情)。

另一方面,你能做的就是进行检查。首先通过初始替换函数运行输入,看看末尾是否有点,如果有点,就替换它。从那里,您可以通过上一个regex来提供它。

所以这就是它的发展。。。

function dotCheck( $url ) {
  $noDotURL = preg_replace( '/'.+$/', '', $url );
  return $noDotURL;
}
urlCheck( dotCheck( $_POST['form'] ) );

其中urlCheck是查看它是否是有效链接结构的主要检查。正则表达式以详细的形式检查作为链接中最后一个字符的点,并将其删除。如果有人输入,这应该有效http://www.google.com.或http://www.google.com.....

愉快的脚本编写。

是。一般来说,这样做:

(<stuff you want to match>)(<character to exclude if at the end>)?$

如果<你想要匹配的东西>以一个量词结尾,该量词需要是非贪婪的,这样排除的最后一个字符将匹配(如果存在)。

然后使用第一个匹配组($1变量)。

然而,我看到您的正则表达式还有一些其他问题。

  • 如果想要匹配多个角色,则需要在角色类中包含/。否则,您只是从第一个/匹配到下一个
  • 我不知道你为什么有一个结束。这使得整个事情都是可选的

这个正则表达式将完成您所描述的:

(/[a-zA-Z0-9._/-]*?)('.)?$

匹配变量$1将包含从第一个/开始到最后的所有内容,但不包括最后一个点(如果有)(该点将在$2中)。

EDIT:正如Adi Inbar所注意到的,您的目标不是使模式失败,而是排除字符串末尾或单词末尾的特定字符:

排除单词末尾的"z"(末尾的几个"z"也被排除)

具有字符类和所有格量词:

(?>[^'Wz]++|z++'B)+ # the most performant way

以排除"."字符串末尾(末尾的几个'.'也被排除在外)

具有前瞻性:

^.+?(?='.*$)

或者带有字符类和所有格量词:

(?>[^.]++|'.++(?!$))+

请注意,您可以很容易地将此表达式调整为所需的更具体的字符类,例如,对于uri:,使用['w.-]

$pattern = '~(?>/['w.-]++)*/(?>['w-]++|'.++(?!$))+/?~';