用于 Java 注释的 Python 正则表达式

标签 python regex annotations

我正在尝试检测文本中的有效 Java 注释。这是我的测试程序(为了简单起见,我目前忽略了所有空格,稍后我将添加它):

txts = ['@SomeName2',                   # match
        '@SomeName2(',                  # no match
        '@SomeName2)',                  # no match 
        '@SomeName2()',                 # match
        '@SomeName2()()',               # no match
        '@SomeName2(value)',            # no match
        '@SomeName2(=)',                # no match
        '@SomeName2("")',               # match
        '@SomeName2(".")',              # no match
        '@SomeName2(",")',              # match
        '@SomeName2(value=)',           # no match
        '@SomeName2(value=")',          # no match
        '@SomeName2(=3)',               # no match
        '@SomeName2(="")',              # no match
        '@SomeName2(value=3)',          # match
        '@SomeName2(value=3L)',         # match
        '@SomeName2(value="")',         # match
        '@SomeName2(value=true)',       # match
        '@SomeName2(value=false)',      # match
        '@SomeName2(value=".")',        # no match
        '@SomeName2(value=",")',        # match
        '@SomeName2(x="o_nbr ASC, a")', # match

        # multiple params:
        '@SomeName2(,value="ord_nbr ASC, name")',                            # no match
        '@SomeName2(value="ord_nbr ASC, name",)',                            # no match
        '@SomeName2(value="ord_nbr ASC, name"insertable=false)',             # no match
        '@SomeName2(value="ord_nbr ASC, name",insertable=false)',            # match
        '@SomeName2(value="ord_nbr ASC, name",insertable=false,length=10L)', # match

        '@SomeName2 ( "ord_nbr ASC, name", insertable = false, length = 10L )',       # match
       ]


#regex = '((?:@[a-z][a-z0-9_]*))(\((((?:[a-z][a-z0-9_]*))(=)(\d+l?|"(?:[a-z0-9_, ]*)"|true|false))?\))?$'
#regex = '((?:@[a-z][a-z0-9_]*))(\((((?:[a-z][a-z0-9_]*))(=)(\d+l?|"(?:[a-z0-9_, ]*)"|true|false))?(,((?:[a-z][a-z0-9_]*))(=)(\d+l?|"(?:[a-z0-9_, ]*)"|true|false))*\))?$'

regex = r"""
    (?:@[a-z]\w*)                               # @ + identifier (class name)
    (
      \(                                        # opening parenthesis
        (
          (?:[a-z]\w*)                          # identifier (var name)
          =                                     # assigment operator
          (\d+l?|"(?:[a-z0-9_, ]*)"|true|false) # either a numeric | a quoted string containing only alphanumeric chars, _, space | true | false
        )?                                      # optional assignment group
      \)                                        # closing parenthesis
    )?$                                         # optional parentheses group (zero or one)
    """


rg = re.compile(regex, re.VERBOSE + re.IGNORECASE)

for txt in txts:
    m = rg.search(txt)
    #m = rg.match(txt)
    if m:
        print "MATCH:   ",
        output = ''
        for i in xrange(2):
            output = output + '[' + str(m.group(i+1)) + ']'
        print output
    else:
        print "NO MATCH: " + txt

所以基本上我所拥有的似乎适用于零个或一个参数。现在我尝试将语法扩展到零个或多个参数,如上一个示例所示。

然后,我复制了表示分配的正则表达式部分,并在第二组到第 n 组的前面添加了一个逗号(该组现在使用 * 而不是 ?):

regex = '((?:@[a-z][a-z0-9_]*))(\((((?:[a-z][a-z0-9_]*))(=)(\d+l?|"(?:[a-z0-9_, ]*)"|true|false))?(,((?:[a-z][a-z0-9_]*))(=)(\d+l?|"(?:[a-z0-9_, ]*)"|true|false))*\))?$'

但是,这不能工作。问题似乎是如何处理第一个元素,因为它必须是可选的,那么像第一个扩展示例 '@SomeName2(,value="ord_nbr ASC, name")' 这样的字符串将是接受了,这是错误的。我不知道如何使第二个到第 n 个分配仅取决于第一个(可选)元素的存在。

可以吗?是这样做的吗?您如何最好地解决这个问题?

谢谢

最佳答案

如果您只是想检测有效的语法,我相信下面的正则表达式将为您提供您想要的匹配项。但我不确定你在这些团体中做什么。您是否希望每个参数值也位于其自己的组中?这会更难,我什至不确定使用正则表达式是否可能。

regex = r'((?:@[a-z][a-z0-9_]*))(?:\((?!,)(?:(([a-z][a-z0-9_]*(=)(?:("[a-z0-9_, ]*")|(true|false)|(\d+l?))))(?!,\)),?)*\)(?!\()|$)'

如果您需要单独的参数/值,您可能需要为此编写一个真正的解析器。

编辑: 这是一个带评论的版本。我还删除了许多捕获组和非捕获组,以使其更易于理解。如果将其与 re.findall() 一起使用,它将返回两组:函数名称和括号中的所有参数:

regex = r'''
(@[a-z][a-z0-9_]*) # function name, captured in group
(                  # open capture group for all parameters
\(                 # opening function parenthesis 
  (?!,)            # negative lookahead for unwanted comma
  (?:              # open non-capturing group for all params
  [a-z][a-z0-9_]*  # parameter name
  =                # parameter assignmentoperators
  (?:"[a-z0-9_, ]*"|true|false|(?:\d+l?)) # possible parameter values
  (?!,\))          # negative lookahead for unwanted comma and closing parenthesis
  ,?               # optional comma, separating params
  )*               # close param non-capturing group, make it optional
\)                 # closing function parenthesis 
(?!\(\))           # negative lookahead for empty parentheses
|$                 # OR end-of-line (in case there are no params)
)                  # close capture group for all parameters
'''

阅读完您对参数的评论后,最简单的事情可能是使用上面的正则表达式来提取所有参数,然后编写另一个正则表达式来提取名称/值对以按照您的意愿进行操作。不过,这也很棘手,因为参数值中有逗号。我将把它作为练习留给读者:)

关于用于 Java 注释的 Python 正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10071295/

相关文章:

python - 为什么 Seaborn 条形图会降低颜色的饱和度?

python - 如何在文本框上方放置 django 字符字段的标签/描述

python - 设置并选择要浏览其图像的画廊

java - 无需编译即可处理java文件中的注释

hibernate - 如何将继承策略与多个子类层相结合

java - Hibernate注释一对多

python - Pygame 名称错误 : name 'image' is not defined

regex - 不匹配 [ 在正则表达式中,尽管被转义

regex - iis重写将所有页面重定向到主页

regex - 从Oracle Varchar2查找和删除非ASCII字符