У меня есть файл, который выглядит примерно так:
select a,b,c FROM Xtable
select a,b,c FROM Vtable
select a,b,c FROM Atable
select a,b,c FROM Atable
select d,e,f FROM Atable
Я хочу получить sortedMap:
{
"Atable":["select a,b,c FROM Atable", "select d,e,f FROM Atable"],
"Vtable":["select a,b,c FROM Vtable"],
"Xtable":["select a,b,c FROM Xtable"]
}
Ключами sortedMap
будут tableName, а значениями будут текстовая строка в списке.
Я начал с этого, но застрял в токенизации строки для сопоставления регулярных выражений:
import re
f = open('mytext.txt', 'r')
x = f.readlines()
print x
f.close()
for i in x:
p = re.search(".* FROM ", i)
//now how to tokenize and get the value that follows FROM
@sln, как мне получить токен сразу после FROM? т.е. Atable, Btable и т. д.
У Python нет sortedMap, у него есть OrderedDict.
@eagertoLearn — Группа 1 = select a,b,c FROM Atable
, Группа 2 = Atable
, а затем сочиняйте, как вам нужно.
Скорее всего, мы не захотим выполнять эту задачу с помощью регулярных выражений, но если захотим, может начинаться с простого выражения, возможно, похожего на:
\"(.+?([a-z]+))\"
Мы бы заменили его на "\2":["\1"],
, а затем добавили бы {}
.
# coding=utf8
# the above tag defines encoding for this document and is for Python 2.x compatibility
import re
regex = r"\"(.+?([a-z]+))\""
test_str = ("\"select a,b,c FROM Xtable\"\n"
"\"select a,b,c FROM Vtable\"\n"
"\"select a,b,c FROM Atable\"\n"
"\"select a,b,c FROM Atable\"\n"
"\"select d,e,f FROM Atable\"")
subst = "\"\\2\":[\"\\1\"],"
# You can manually specify the number of replacements by changing the 4th argument
result = re.sub(regex, subst, test_str, 0, re.MULTILINE | re.IGNORECASE)
if result:
print (result)
# Note: for Python 2.7 compatibility, use ur"" to prefix the regex and u"" to prefix the test string and substitution.
Если это выражение не нужно, его можно модифицировать/изменить в regex101.com.
jex.im визуализирует регулярные выражения:
если не регулярное выражение, как еще вы хотели бы сделать тогда?
и это не удается, если я удаляю двойные кавычки, например select a,b,c FROM Xtable
Результатом будет строка, а не dict.
Вы можете использовать комбинацию defaultdict
и регулярных выражений. Пусть lines
будет списком ваших строк:
from collections import defaultdict
pattern = "(select .+ from (\S+).*)"
results = defaultdict(list)
for line in lines:
query, table = re.findall(pattern, line.strip(), flags=re.I)[0]
results[table].append(query)
На самом деле, правильный способ чтения файла:
with open('mytext.txt') as infile:
for line in infile:
query, table = re.findall(pattern, line.strip(), flags=re.I)[0]
results[table].append(query)
Результат, естественно, defaultdict
. Если вы хотите преобразовать его в упорядоченный словарь, вызовите конструктор словаря:
from collections import OrderedDict
OrderedDict(sorted(results.items()))
#OrderedDict([('Atable', ['select a,b,c FROM Atable', ...
Вы можете сделать pattern
более надежным, чтобы отслеживать запятые, действительные идентификаторы и т. д.
это не похоже на отсортированный дикт?
прекрасно работает. пару вещей, которые я заметил с моими тестовыми данными. существует один тип запроса, например «выбрать a, b, c из TableX, где id = 10» и «выбрать a, b (выбрать d, e из таблицы Y) из TableX». В обоих случаях я ожидаю, что «TableX» будет ключом и значением для запроса.
так что в основном получите следующий токен из последнего «FROM» в операторе select. С текущим я получаю ключ как «TableX, где id = 10», что неверно.
вы упомянули, что эту проблему трудно решить, и вы сделали это за минуту :). Это прекрасно работает. Сейчас я работаю над большим файлом. Я приму это, как только оно будет закончено. Спасибо еще раз
Вот
(.*FROM[ \t]+(\S+))