首页 > 解决方案 > re.DOTALL 没有选择换行符

问题描述

这是我正在使用的字符串: string =

'\n\n <!----><div class="screen-reader-text" ng-if="::(ctrl.messageViewModel.isChat || ctrl.messageViewModel.isReply)" role="heading" aria-level="5">\n\n\nADMIN_COMMAND STOP\n\n, reply from YATIN </div><!---->\n\n <!--Chat head-->\n <div class="media-left" ng-class="{ \'hide-media-left\' : ctrl.messageViewModel.editFormVisible }">\n <!-- Person icon -->\n \n <!---->\n \n </div>\n\n <div class="ts-message-thread-body align-item-left" data-tid="messageThreadBody" ng-class="{\'has-attachments\': ctrl.messageViewModel.hasAttachments} ">\n <!--EditMessage-->\n <!---->\n <!--EditMessage-->\n <!----><div id="messageBody" class="message-body message-body-width" ng-if="!ctrl.messageViewModel.editFormVisible" simple-mouseenter="!ctrl.isInteropChat &amp;&amp; ctrl.messageReactionsEnabled &amp;&amp; ctrl.showMessageActions($event, this)" ng-mouseleave="!ctrl.isInteropChat &amp;&amp; ctrl.messageReactionsEnabled &amp;&amp; ctrl.hoverOutMessageBodyHandler($event)">\n <!----><div class="message-body-top-row padded-content" ng-if="!ctrl.isHiddenByDlp" ng-class="{ \'unread-message\': ctrl.messageViewModel.isNewMessage,\n \'has-reactions\': ctrl.messageReactionsEnabled &amp;&amp; ctrl.messageViewModel.messageHasReaction}">\n <div class="top-row-text-container" ng-class="{\'single-line-truncation\': ctrl.messageReactionsEnabled &amp;&amp; ctrl.messageViewModel.isRightRail}">\n <!--Name-->\n <div class="ts-msg-name app-small-font" data-tid="threadBodyDisplayName" dir="auto">\n 等等...

主要感兴趣的部分是:(>\n\n\nADMIN_COMMAND STOP\n\n, reply from在),我想从中得到ADMIN_COMMAND STOP

ADMIN_COMMAND STOP部分可以是任意长度并且可以有数字。此外,\n它之前和之后可以有几个 s。

其他输入可以有:

>\n\n\nADMIN_COMMAND REFRESH\n\n, reply from

>0, reply from

>\n\n\n\nADMIN_COMMAND STOP\n\n\n, reply from

我想得到的输出:

ADMIN_COMMAND STOP

ADMIN_COMMAND REFRESH

0

我想出了这个:

re.findall(">.*([A-Z 0-9]*).*, reply from",string,re.DOTALL)

我的逻辑:

然后检查一个>,零个或多个任何字符(包括\n)然后,找到零个或多个大写字母/数字,然后再次检查零个或多个任何字符(包括\n

标签: pythonregex

解决方案


确实找到了匹配项,因为它不返回空列表:

>>> import re
>>> string = ">\n\n\n\nADMIN_COMMAND STOP\n\n\n, reply from"
>>> re.findall(">.*([A-Z 0-9]*).*, reply from",string,re.DOTALL)
['']

问题是捕获组([A-Z 0-9]*)匹配零个字符,因为所有字符都已经被.*它之前的贪婪消耗掉了。

[^A-Z 0-9]您可以通过在捕获组之前使用否定字符类来修复它。现在它不再匹配任何东西,因为_inADMIN_COMMAND不在字符类中。修复后,它按预期工作:

>>> re.findall(">[^A-Z 0-9_]*([A-Z 0-9_]*).*, reply from",string,re.DOTALL)
['ADMIN_COMMAND STOP']

请注意,在这种情况下,非贪婪匹配 ,.*?似乎没有达到预期的效果。即使我们.*?在捕获组之前和之后都放置,所有字符最终都会被最终匹配,.*?尽管*中间有贪婪:

>>> re.findall(">.*?([A-Z 0-9_]*).*?, reply from",string,re.DOTALL)
['']

我不太明白为什么。


推荐阅读