Py学习  »  Python

使用python中的正则表达式在文件中选择一组特定的字符

jayz • 3 年前 • 1306 次点击  

在我的代码中,我有如下定义的视图。

VIEW Company_Person_Sd IS
   Prompt = 'Company'
   Company.Prompt = 'Company ID'
SELECT company_id                          company_id,
       emp_no                              emp_no,
       Get_Person(company_id, emp_no)      person_id,
       cp.rowid                            objid,
       to_char(cp.rowversion)              objversion,
       rowkey                              objkey
FROM   companies cp;

一个文件中可以定义多个视图(通常有20个或更多)。

我对下面这样的方法做了同样的事情,使用下面的正则表达式。(而且效果很好)

methodRegex = r"^\s*((FUNCTION|PROCEDURE)\s+(\w+))(.*?)BEGIN(.*?)^END\s*(\w+);"

methodMatches = re.finditer(methodRegex, fContent, re.DOTALL | re.MULTILINE | re.IGNORECASE | re.VERBOSE)
        
        for methodMatchNum, methodMatch in enumerate(methodMatches, start=1):
            methodContent=methodMatch.group()
            methodNameFull=methodMatch.group(1)
            methodType=methodMatch.group(2)
            methodName=methodMatch.group(3)

方法示例

PROCEDURE Prepare___ (
   attr_ IN OUT VARCHAR2 )
IS
  ----
BEGIN
   --
END Prepare___;

PROCEDURE Insert___ (
   attr_ IN OUT VARCHAR2 )
IS
  ----
BEGIN
   --
END Insert___;

当我尝试对视图执行相同操作时,它会给出错误的输出。 事实上,我找不到如何抓住风景的尽头。我也尝试使用分号,结果输出错误。

查看我的正则表达式

 viewRegex = r"^\s*(VIEW\s+(\w+))(.*?)SELECT(.*?)^FROM\s*(\w+);"

请帮我找出哪里做错了。提前谢谢。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/131719
文章 [ 2 ]  |  最新文章 3 年前
Tranbi
Reply   •   1 楼
Tranbi    4 年前

你找不到匹配的 viewRegex 因为它只在只有单词字符时匹配( [a-zA-Z0-9_] )中间 FROM ; .而您的示例中也包含空格。所以也要考虑空格:

viewRegex = r"^\s*(VIEW\s+(\w+))(.*?)SELECT(.*?)^FROM\s*([\w\s]+);"
The fourth bird
Reply   •   2 楼
The fourth bird    4 年前

如果一个文件中有很多视图,另一个选项是防止使用 .*? 具有 re.DOTALL 防止不必要的回溯。

相反,您可以匹配 VIEW SELECT FROM 检查介于两者之间的内容是否是另一个关键字,以防止使用负面前瞻进行过多匹配(假设这些不会发生在两者之间)

对于FROM之后的最后一部分,可以匹配单词字符,可以选择使用空格字符和单词字符重复。

^(VIEW\s+(\w+))(.*(?:\n(?!SELECT|VIEW|FROM).*)*)\nSELECT\s+(.*(?:\n(?!SELECT|VIEW|FROM).*)*)\nFROM\s+(\w+(?:\s+\w+));

模式匹配:

  • ^ 字符串开头
  • (VIEW\s+(\w+)) 捕获组以供查看,后面是一组字符
  • (.*(?:\n(?!SELECT|VIEW|FROM).*)*) 捕获与其余行匹配的组,以及所有不以关键字开头的行
  • \nSELECT\s+ 匹配换行符,选择1+空格
  • (.**:\n(?!选择|查看|自)。*)*) 捕获与其余行匹配的组,以及所有不以关键字开头的行
  • \nFROM\s+ 匹配换行符、FROM和1+空格字符
  • (\w+(?:\s+\w+)) ; 为FROM的值捕获组,匹配1+个单词字符,并可选地按空格字符和单词字符重复

Regex demo

例如(您可以省略 re.VERBOSE 重新。多塔尔 )

import re

methodRegex = r"^^(VIEW\s+(\w+))(.*(?:\n(?!SELECT|VIEW|FROM).*)*)\nSELECT\s+(.*(?:\n(?!SELECT|VIEW|FROM).*)*)\nFROM\s+(\w+(?:\s+\w+));"
fContent = ("VIEW Company_Person_Sd IS\n"
            "   Prompt = 'Company'\n"
            "   Company.Prompt = 'Company ID'\n"
            "SELECT company_id                          company_id,\n"
            "       emp_no                              emp_no,\n"
            "       Get_Person(company_id, emp_no)      person_id,\n"
            "       cp.rowid                            objid,\n"
            "       to_char(cp.rowversion)              objversion,\n"
            "       rowkey                              objkey\n"
            "FROM   companies cp;")
methodMatches = re.finditer(methodRegex, fContent, re.MULTILINE | re.IGNORECASE)

for methodMatchNum, methodMatch in enumerate(methodMatches, start=1):
    methodContent = methodMatch.group()
    methodNameFull = methodMatch.group(1)
    methodType = methodMatch.group(2)
    methodName = methodMatch.group(3)