Выберите определенный набор символов в файле с помощью регулярных выражений в python

#python #regex

#python #регулярное выражение

Вопрос:

В моем коде у меня есть представления, определенные, как показано ниже.

 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 или более).

Я хочу получить полное представление, используя регулярное выражение в python.

Я сделал то же самое с методом, как показано ниже, используя следующее регулярное выражение. (и это сработало нормально)

 methodRegex = r"^s*((FUNCTION|PROCEDURE)s (w ))(.*?)BEGIN(.*?)^ENDs*(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*(VIEWs (w ))(.*?)SELECT(.*?)^FROMs*(w );"
 

Пожалуйста, помогите мне выяснить, где я делаю это неправильно. Заранее спасибо.

Ответ №1:

Если у вас много представлений в одном файле, другим вариантом является предотвращение использования .*? with re.DOTALL для предотвращения ненужного возврата.

Вместо этого вы можете сопоставить части от VIEW SELECT до FROM , проверяя, что то, что находится между ними, не является другим одним из ключевых слов, чтобы предотвратить слишком сильное сопоставление с использованием отрицательного прогноза (при условии, что они не могут встречаться между ними)

Для последней части после FROM вы можете сопоставить символы word, необязательно повторяющиеся символами пробела и снова символами word.

 ^(VIEWs (w ))(.*(?:n(?!SELECT|VIEW|FROM).*)*)nSELECTs (.*(?:n(?!SELECT|VIEW|FROM).*)*)nFROMs (w (?:s w ));
 

Шаблон соответствует:

  • ^ Начало строки
  • (VIEWs (w )) Группа захвата для ПРЕДСТАВЛЕНИЯ, за которой следует группа для символов слова
  • (.*(?:n(?!SELECT|VIEW|FROM).*)*) Группа захвата, соответствующая остальным строкам, и все строки, которые не начинаются с ключевого слова
  • nSELECTs Сопоставьте новую строку, ВЫБЕРИТЕ и 1 пробел cahr
  • (.*(?:n(?!SELECT|VIEW|FROM).*)*) Группа захвата, соответствующая остальным строкам, и все строки, которые не начинаются с ключевого слова
  • nFROMs Сопоставьте символы новой строки, FROM и 1 пробел
  • (w (?:s w )) ; Группа захвата для значения FROM, совпадающего с 1 символами word и, при необходимости, повторяющегося с помощью пробельных символов и символов word

Демонстрация регулярных выражений

Например (вы можете опустить re.VERBOSE и re.DOTALL )

 import re

methodRegex = r"^^(VIEWs (w ))(.*(?:n(?!SELECT|VIEW|FROM).*)*)nSELECTs (.*(?:n(?!SELECT|VIEW|FROM).*)*)nFROMs (w (?:s w ));"
fContent = ("VIEW Company_Person_Sd ISn"
            "   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                              objkeyn"
            "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)
 

Комментарии:

1. Хорошее объяснение. Спасибо

Ответ №2:

Вы не получите никакого совпадения с viewRegex , потому что оно совпадает только тогда, когда между и есть только символы word ( [a-zA-Z0-9_] ) FROM ; . В то время как ваш пример также включает пробел. Поэтому также учитывайте пробелы:

 viewRegex = r"^s*(VIEWs (w ))(.*?)SELECT(.*?)^FROMs*([ws] );"
 

Комментарии:

1. Спасибо, и все сработало нормально.