Python正则表达式中的反斜杠

时间:2016-06-10 19:10:41

标签: python regex

我正在写一个快速的Python脚本来对我们的一些Hibernate映射文件进行一些检查。我试图使用这个Python来获取POJO的表名,无论其类路径是否已完全定义:

searchObj = re.search(r'<class name="(.*\\.|)' + pojo + '".*table="(.*?)"', contents)

然而 - 说pojo是&#39; MyObject&#39; - 正则表达式与此行不匹配:

<class name="com.place.package.MyObject" table="my_cool_object" dynamic-insert="true" dynamic-update="true">

如果我打印字符串(在Pdb中停止)我正在搜索,我看到了:

'<class name="(.*\\\\.|)MyObject".*table="(.*?)"'

我很困惑这里出了什么问题。首先,我的印象是&#39; r&#39;前缀使得反斜杠不会被转义。即便如此,如果我删除其中一个反斜杠,使得我的搜索字符串为:

searchObj = re.search(r'<class name="(.*\.|)' + pojo + '".*table="(.*?)"', contents)

搜索的字符串变为

'<class name="(.*\\.|)MyObject".*table="(.*?)"'

它仍然没有返回匹配。这里出了什么问题?我打算使用的正则表达式在regex101.com上运行(在明显有问题的区域只有一个反斜杠。)任何想法在这里出了什么问题?

2 个答案:

答案 0 :(得分:2)

Pythex上,我尝试了这个正则表达式:

<class name="(.*)\.MyObject" table="([^"]*)"

在这个字符串上:

<class name="com.place.package.MyObject" table="my_cool_object" dynamic-insert="true" dynamic-update="true">

并获得了这两个匹配捕获:

  1. com.place.package
  2. my_cool_object
  3. 所以我认为在你的情况下,这一行

    searchObj = re.search(r'<class name="(.*)\.' + pojo + '"table="([^"]*)"', contents)
    

    将产生您想要的结果。

    关于令人困惑的反斜杠 - 在Python文档7.2. re — Regular expression operations上添加两个然后四个显示,它解释了r''是“原始字符串表示法”,用于规避Python的常规字符转义,使用反斜杠。所以:

    • '\\'表示“由一个反斜杠组成的字符串”,因为字符串中的第一个反斜杠会转义第二个反斜杠。 Python看到了第一个反斜杠,并认为“下一个角色是一个特殊的角色”;然后它看到第二个并说,'特殊字符是一个实际的反斜杠'。它存储为单个字符\。如果你要求Python打印它,它将转义输出并显示"\\"
    • r'\\'表示“由两个实际反斜杠组成的字符串。它存储为字符\,后跟字符\。如果你要求Python打印它,它将转义输出并显示"\\\\"

答案 1 :(得分:2)

鉴于此:

re.search(r'<class name="(.*\\.|)' + pojo + '".*table="(.*?)"', contents)

模式的第一部分解释如下:

1. class name="    a literal string beginning with c and ending with "
2. (               the beginning of a group
3.   .*                zero or more of any characters
4.   \\                a literal single slash
5.   .                 any single character
6. OR
7.                     nothing
8. )               end of the group

由于您要搜索的字符串没有文字反斜杠,因此不匹配。

如果您希望\\.表示“文字句号”,则需要一个反斜杠,因为它位于原始字符串中:\.

此外,用管道结束组似乎很奇怪。我不确定你认为那是在做什么。如果您的意思是说“任意数量的字符以点结尾,或者什么都没有”,您可以使用(.*\.)?执行此操作,因为?表示“零或前一个匹配”。

这似乎对我有用:

import re
contents1 = '''<class name="com.place.package.MyObject" table="my_cool_object" dynamic-insert="true" dynamic-update="true">'''
contents2 = '''<class name="MyObject" table="my_cool_object" dynamic-insert="true" dynamic-update="true">'''
pojo="MyObject"

pattern = r'<class name="(.*\.)?' + pojo + '.*table="(.*?)"'

assert(re.search(pattern, contents1))
assert(re.search(pattern, contents2))