регулярное выражение для питона

Я пишу regx для удаления квалификатора теста и дополнительного разделителя из строки.

У меня есть образец, как показано ниже,

"ID"~"Name"~"DESC"
1~2014~13~"DS"~DF"
1~2014~13~"DS"~"DF" 
"1ABCA~B C"~"ERTE"
"2"~"XYZ"~"ABC~ is~ bother"
"3"~"YYZ"~"MEL O CRÈME DOUGHNUTS RECLASS"
4~"XAA"~"sf~sd sdfsf"
5~"TES"~"SFSFSF"sdfsf"
6~"ABC"SDDSL~"dfadf"

ожидаемый результат,

ID~Name~DESC
1~2014~13~DS~DF
1~2014~13~DS~DF
1ABCA B C~ERTE
2~XYZ~ABC  is  bother
3~YYZ~MEL O CRÈME DOUGHNUTS RECLASS
4~XAA~sf sd sdfsf
5~TES~SFSFSF"sdfsf
6~ABCSDDSL~dfadf

Я написал ниже код для того же,

import re

delimiter = '~'
pattern = re.compile(r'"' + delimiter + r'"')
pattern1 = re.compile(r'"[^"]*(?:""[^"]*)*"')

with open("source file path here ", "r") as \
        test:
    for line in test:
        fields = re.split(pattern, line)
        print(fields)
        output = ""
        if re.match('^[^"]', line):
            matches = re.findall(pattern1, line)
            print(matches)
            for match in matches:
                line = re.sub(match, re.sub('^["]|["]$', "", match), line)
            print(line)
        else:
            lastfield = fields[-1]
            for field in fields:
                if field != lastfield:
                    field = re.sub('^["]|["]$', "", field)
                    output = output + re.sub('[' + delimiter + ']', " ", field) \
                        + delimiter
                else:
                    field = re.sub('^["]|["]$', "", field)
                    output = output + re.sub('[' + delimiter + ']', " ", field)
        print(output)

ищем оптимальный способ сделать это и код, который будет обрабатывать все шаблоны.


person rsarda    schedule 15.06.2018    source источник
comment
Почему ожидается, что вторая строка превратится в 1~2014~13~DS~DF? Последний " не спарен. Или третья часть должна остаться в последнем поле?   -  person Wiktor Stribiżew    schedule 15.06.2018
comment
@WiktorStribiżew, потому что при загрузке этих данных в систему это создаст проблему, поэтому хотелось удалить кавычки, которые не являются частью данных. Это проблема уровня данных, которую нам нужно решить.   -  person rsarda    schedule 15.06.2018
comment
Не могли бы вы написать правила замены в вопросе? Должен ли 1~2014~13~DS~DF действительно дублироваться?   -  person Wiktor Stribiżew    schedule 15.06.2018
comment
@WiktorStribiżew, извините, это моя вина, я пропустил один шаблон для записи: 1~2014~13~DS~DF   -  person rsarda    schedule 15.06.2018
comment
@WiktorStribiżew правила удаляют ненужный разделитель и кавычки, которые не являются частью данных, если кавычки входят в состав строки, нам нужно сохранить это, поскольку данные неизменяемы.   -  person rsarda    schedule 15.06.2018
comment
Здесь все еще есть путаница: если последний " во второй строке должен исчезнуть, почему он должен оставаться в предпоследней строке? Извините, этот вопрос не ясен, и только вы можете ответить на него. Мы не знаем, как вы определяете, что неизменно, а что нежелательно.   -  person Wiktor Stribiżew    schedule 15.06.2018
comment
Нам понадобится спецификация вашего формата... и я имею в виду спецификацию... не простое описание. Иначе это слишком непонятно...   -  person mroman    schedule 15.06.2018
comment
@WiktorStribiżew Есть два типа данных: числовые и строковые, мы получили много файлов, некоторые из которых содержат двойные кавычки для числовых и строковых данных, а также есть несколько файлов, которые содержат двойные кавычки только для строк. Проблема в том, что если данные содержат дополнительный разделитель, нам нужно обработать это, и если в строке есть кавычки, нам нужно оставить это как есть. Иногда из-за некоторых проблем кавычки могут отсутствовать в начале или в конце, нам также нужно это исправить.   -  person rsarda    schedule 15.06.2018
comment
@WiktorStribiżew во второй строке кавычки находятся в конце строки, что означает, что она недействительна и ее необходимо удалить, если вы посмотрите на последние кавычки, присутствующие в строке, в этом разница.   -  person rsarda    schedule 15.06.2018
comment
Помимо того факта, что вывод вашего образца не совпадает с вводом (почему вторая строка дублируется?), вы на самом деле не задаете вопрос. Пожалуйста, укажите проблему с вашим кодом. ищете способ оптимизации - пожалуйста, укажите, какую проблему вы заметили при профилировании. Или вы просто ищете человека, который проверит ваш код?   -  person Ruud Helderman    schedule 15.06.2018
comment
@mroman изучите два приведенных выше комментария, если все еще неясно, дайте мне знать, и я подробно изложу проблему.   -  person rsarda    schedule 15.06.2018
comment
@rudd holderman Я уже упоминал в первом комментарии, что по ошибке пропустил одну строку, поэтому она показывает повторяющуюся строку.   -  person rsarda    schedule 15.06.2018
comment
Почему 1ABCA B C~ERTE ожидается от "1ABCA~B C"~"ERTE"? Я бы ожидал "1ABCA~B C~ERTE. То же самое о 2~XYZ~ABC is bother - я бы ожидал 2~XYZ~ABC~ is~ bother. Я не могу получить формулу. Я попробовал ideone.com/4qlIks.   -  person Wiktor Stribiżew    schedule 16.06.2018
comment
@WiktorStribiżew сначала вы можете разделить поля, используя двойные кавычки и разделитель в приведенном выше примере, 2 ~ XYZ ~ ABC ~ ~ беспокоит, если вы разделите, вы получите 2 XYZ ABC ~ is ~ здесь, если удалить двойные кавычки и загрузить данные как есть. создать проблему, так как последняя часть с дополнительным разделителем при загрузке будет разделена на три столбца. так что любой разделитель, входящий в кавычки, является дополнительным и должен быть удален.   -  person rsarda    schedule 16.06.2018
comment
Если вы говорите, что ~ между кавычками нужно удалить, то 4~"XAA"~"sf~sd sdfsf" должно превратиться в 4~XAA~sf sd sdfsf, почему вы ожидаете 4~XAA~sf~sd sdfsf? Я попробовал ideone.com/j9f6EH.   -  person Wiktor Stribiżew    schedule 16.06.2018
comment
@WiktorStribiżew да, ты прав.   -  person rsarda    schedule 17.06.2018
comment
@WiktorStribiżew увидел ваш код на ideone.com/j9f6EH. не могли бы вы объяснить.   -  person rsarda    schedule 17.06.2018
comment
Я удаляю символы ~ между квалификаторами полей (двойные кавычки), а затем удаляю все ", у которых нет " или ~ в конце поля (не уверен, что это то, что вам нужно, поэтому все еще не решается опубликовать ответ).   -  person Wiktor Stribiżew    schedule 17.06.2018
comment
@WiktorStribiżew опубликуйте свой ответ, я видел, что я думаю, что он работает, поэтому опубликуйте ответ здесь   -  person rsarda    schedule 17.06.2018


Ответы (1)


Я думаю, вы можете удалить все ~ внутри квалификаторов поля с помощью

(?m)(?:(?<=^)|(?<=~))"(.*?)"(?=$|~)

Подробнее

  • (?m) - режим re.M включен, чтобы ^ совпадало с началом строки, а $ совпадало с концом строки (удалить, если строки обрабатываются построчно)
  • (?:(?<=^)|(?<=~)) - начало строки или позиция, непосредственно предшествующая ~
  • " - двойная кавычка
  • (.*?) - Группа 1: любые 0+ символов, кроме новой строки, как можно меньше
  • " - двойная кавычка
  • (?=$|~) — конец строки или место, за которым сразу следует ~.

а затем удалите все ненужные двойные кавычки с помощью

(?m)(?:(?<=^)|(?<=~))"|"(?=$|~)|"(?=[^\n"~]+(?:~|$))

Подробнее

  • (?m) - модификатор re.M (убрать, если строки обрабатываются построчно)
  • (?:(?<=^)|(?<=~))" - двойная кавычка в начале строки или сразу после ~
  • "(?=$|~)| - " в конце строки или перед ~
  • "(?=[^\n"~]+(?:~|$)) - ", за которым следует 1 или более символов, кроме LF (удалить, если строки обрабатываются построчно), " и ~, а затем ~ или конец строки.

Thin one можно использовать для сопоставления подстрок, а затем удалить все ~ с пробелами, используя .replace('~', ' ') внутри метода обратного вызова replace.

См. демонстрацию Python:

import re
rx_0 = r"""(?m)(?:(?<=^)|(?<=~))"(.*?)"(?=$|~)"""
rx = r"""(?m)(?:(?<=^)|(?<=~))"|"(?=$|~)|"(?=[^\n"~]+(?:~|$))"""
s = ("\"ID\"~\"Name\"~\"DESC\"\n"
    "1~2014~13~\"DS\"~DF\"\n"
    "1~2014~13~\"DS\"~\"DF\"\n"
    "\"1ABCA~B C\"~\"ERTE\"\n"
    "\"2\"~\"XYZ\"~\"ABC~ is~ bother\"\n"
    "\"3\"~\"YYZ\"~\"MEL O CRÈME DOUGHNUTS RECLASS\"\n"
    "4~\"XAA\"~\"sf~sd sdfsf\"\n"
    "5~\"TES\"~\"SFSFSF\"sdfsf\"\n"
    "6~\"ABC\"SDDSL~\"dfadf\"")

print( re.sub(rx, "", re.sub(rx_0, lambda x: x.group(1).replace('~', ' '), s)))

Выход:

ID~Name~DESC
1~2014~13~DS~DF
1~2014~13~DS~DF
1ABCA B C~ERTE
2~XYZ~ABC  is  bother
3~YYZ~MEL O CRÈME DOUGHNUTS RECLASS
4~XAA~sf sd sdfsf
5~TES~SFSFSFsdfsf
6~ABC"SDDSL dfadf
person Wiktor Stribiżew    schedule 17.06.2018