Как очистить комментарии от сырого файла sql
У меня проблема с комментариями очистки и пустые строки из уже существующего sql файла.
Файл имеет более 10 тыс. Строк, поэтому его очистка вручную не является вариантом.
У меня немного python script, но я понятия не имею, как обрабатывать комментарии внутри многострочных вставок.
Код:
f = file( 'file.sql', 'r' )
t = filter( lambda x: not x.startswith('--') \
and not x.isspace()
, f.readlines() )
f.close()
t #<- here the cleaned data should be
Как это должно работать:
Это нужно очистить:
-- normal sql comment
Это должно оставаться таким:
CREATE FUNCTION func1(a integer) RETURNS void
LANGUAGE plpgsql
AS $$
BEGIN
-- comment
[...]
END;
$$;
INSERT INTO public.texts (multilinetext) VALUES ('
and more lines here \'
-- part of text
\'
[...]
');
Ответы
Ответ 1
Попробуйте sqlparse модуль.
Обновленный пример: оставить комментарии внутри значений вставки и комментарии в блоках CREATE FUNCTION. Вы можете изменить настройки поведения:
import sqlparse
from sqlparse import tokens
queries = '''
CREATE FUNCTION func1(a integer) RETURNS void
LANGUAGE plpgsql
AS $$
BEGIN
-- comment
END;
$$;
SELECT -- comment
* FROM -- comment
TABLE foo;
-- comment
INSERT INTO foo VALUES ('a -- foo bar');
INSERT INTO foo
VALUES ('
a
-- foo bar'
);
'''
IGNORE = set(['CREATE FUNCTION',]) # extend this
def _filter(stmt, allow=0):
ddl = [t for t in stmt.tokens if t.ttype in (tokens.DDL, tokens.Keyword)]
start = ' '.join(d.value for d in ddl[:2])
if ddl and start in IGNORE:
allow = 1
for tok in stmt.tokens:
if allow or not isinstance(tok, sqlparse.sql.Comment):
yield tok
for stmt in sqlparse.split(queries):
sql = sqlparse.parse(stmt)[0]
print sqlparse.sql.TokenList([t for t in _filter(sql)])
Вывод:
CREATE FUNCTION func1(a integer) RETURNS void
LANGUAGE plpgsql
AS $$
BEGIN
-- comment
END;
$$;
SELECT * FROM TABLE foo;
INSERT INTO foo VALUES ('a -- foo bar');
INSERT INTO foo
VALUES ('
a
-- foo bar'
);
Ответ 2
Добавление обновленного ответа :)
import sqlparse
sql_example = """--comment
SELECT * from test;
INSERT INTO test VALUES ('
-- test
a
');
"""
print sqlparse.format(sql_example, strip_comments=True).strip()
Выход:
SELECT * from test;
INSERT INTO test VALUES ('
-- test
a
');
Он достигает того же результата, но также охватывает все другие angular случаи и более краткий
Ответ 3
Это пример ответа samplebias, который работает с вашим примером:
import sqlparse
sql_example = """--comment
SELECT * from test;
INSERT INTO test VALUES ('
-- test
a
');
"""
new_sql = []
for statement in sqlparse.parse(sql_example):
new_tockens = [stm for stm in statement.tokens
if not isinstance(stm, sqlparse.sql.Comment)]
new_statement = sqlparse.sql.TokenList(new_tockens)
new_sql.append(new_statement.to_unicode())
print sqlparse.format("\n".join(new_sql))
Вывод:
SELECT * from test;
INSERT INTO test VALUES ('
-- test
a
');
Ответ 4
Это можно сделать с помощью регулярных выражений. Сначала вам нужно разбить файл по строкам, после чего вы можете разделить файл на комментарии. Следующая программа Perl делает это:
#! /usr/bin/perl -w
# Read hole file.
my $file = join ('', <>);
# Split by strings including the strings.
my @major_parts = split (/('(?:[^'\\]++|\\.)*+')/, $file);
foreach my $part (@major_parts) {
if ($part =~ /^'/) {
# Print the part if it is a string.
print $part;
}
else {
# Split by comments removing the comments
my @minor_parts = split (/^--.*$/m, $part);
# Print the remaining parts.
print join ('', @minor_parts);
}
}
Ответ 5
# Remove comments i.e. lines beginning with whitespace and '--' (using multi-line flag)
re.sub('^\s*--.*\n?', '', query, flags=re.MULTILINE)
Строка Regex объясняется:
- ^ начало строки
- \s whitespace
- \s * нулевые или более пробельные символы
- - два hypens (статический шаблон строки)
- . * ноль или более любых символов (т.е. остальная часть строки)
- \n символ новой строки
- ? конец строки
- flags = re.M - многострочный модификатор
"Когда указано, символ шаблона '^' совпадает в начале строки и в начале каждой строки (сразу после каждой новой строки)"
Подробнее см. документацию по регулярным выражениям Python:
https://docs.python.org/3/library/re.html