как понимать re.sub (& ldquo; & rdquo ;, & ldquo; - & rdquo ;, & ldquo; abxc & rdquo;) в python [duplicate]

Вам придется использовать более сложный метод сериализации, чем приведение класса к char* и запись его в файл, если ваш класс содержит любые экзогенные данные (string). И вы правы в том, почему вы получаете ошибку сегментации.

Я бы сделал функцию-член, которая будет принимать fstream и читать данные из нее, а также обратную функцию, которая возьмите fstream и напишите его содержимое для его восстановления позже, например:

class MyClass {
pubic:
    MyClass() : str() { }

    void serialize(ostream& out) {
        out << str;
    }

    void restore(istream& in) {
        in >> str;
    }

    string& data() const { return str; }

private:
    string str;
};

MyClass c;
c.serialize(output);

// later
c.restore(input);

Вы также можете определить operator<< и operator>> для работы с istream и ostream для сериализации и восстановления вашего класса, если вы хотите использовать этот синтаксический сахар.

2
задан thuzhf 11 May 2015 в 06:16
поделиться

4 ответа

Лучшее объяснение этого поведения, о котором я знаю, это от пакета regex PyPI, который предназначен для в конечном итоге заменить re (хотя это было путь в течение длительного времени).

Иногда неясно, как следует обрабатывать совпадения нулевой ширины. Например, должно совпадать 0 символов сразу после сопоставления> 0 символов?

Большинство реализаций регулярных выражений следуют примеру Perl (PCRE), но иногда модуль re не работает. По-видимому, поведение Perl является наиболее распространенным (и модуль re иногда определенно ошибочным), поэтому в версии 1 модуль регулярных выражений следует за поведением Perl, тогда как в версии 0 он следует за традиционным поведением.

Примеры:

# Version 0 behaviour (like re)
>>> regex.sub('(?V0).*', 'x', 'test')
'x'
>>> regex.sub('(?V0).*?', '|', 'test')
'|t|e|s|t|'

# Version 1 behaviour (like Perl)
>>> regex.sub('(?V1).*', 'x', 'test')
'xx'
>>> regex.sub('(?V1).*?', '|', 'test')
'|||||||||'

(?VX) устанавливает флаг версии в регулярном выражении. Второй пример - то, что вы ожидаете, и, предположительно, это то, что делает PCRE. Python re несколько нестандартен и хранится, поскольку он, вероятно, связан исключительно с обратной совместимостью. Я нашел пример чего-то подобного re.split).

4
ответ дан Veedrac 15 August 2018 в 22:42
поделиться
  • 1
    Это сильно отличается от re. Но я думаю, что regex действительно выполняет право . :) – thuzhf 11 May 2015 в 05:54

Для вашего нового редактируемого вопроса:

.*? может соответствовать любому числу символов, включая ноль. Итак, что он делает, он соответствует нулевым символам в каждой позиции в строке: перед «a», между «a» и «b» и т. Д. Он заменяет каждое из этих совпадений нулевой ширины дефисом, давая результат вы видите.

Регулярное выражение не пытается сопоставлять каждый символ по одному; он пытается совместить в каждой позиции в строке. Ваше регулярное выражение позволяет ему соответствовать нулевым символам. Поэтому он соответствует нулю в каждой позиции и переходит к следующему. Кажется, вы думаете, что в строке, такой как «abc», есть одна позиция перед «b», одна позиция «внутри» «b» и одна позиция после «b», но нет позиции «внутри» «индивидуальный характер. Если он соответствует нулевым символам, начинающимся до «b», следующая вещь, которую он пытается, должна начинаться после «b». Нет никакого способа заставить регулярное выражение совместить семь раз в трехсимвольной строке, потому что есть только четыре позиции, которые можно сопоставить.

3
ответ дан BrenBarn 15 August 2018 в 22:42
поделиться
  • 1
    Поскольку '.' соответствует любому символу, почему он не заменяет «a», «b» и «c» на «-» и заменяет только символ нулевой ширины на «-»? – thuzhf 11 May 2015 в 05:27
  • 2
    @thuzhf: Я добавил немного к моему ответу. . может соответствовать любому символу, но вы позволяете ему соответствовать нулю, так оно и есть. Нет позиции "внутри" индивидуальный характер для его соответствия. Если он находит совпадение до «b», он затем пытается найти его после. Если вы хотите, чтобы он соответствовал букве «b», вы должны позволить регулярному выражению потреблять «b & quot; вместо того, чтобы ничего не сопоставлять. – BrenBarn 11 May 2015 в 05:28
  • 3
    @thuzhf: Я не понимаю, о чем вы просите. – BrenBarn 11 May 2015 в 05:40
  • 4
    Просто проигнорируйте этот комментарий. Спасибо вам за интерпретацию! – thuzhf 11 May 2015 в 06:16

Чтобы выяснить ответ Veedrac , различная реализация имеет различную обработку совпадений нулевой ширины в операциях FindAll (или ReplaceAll). Два поведения можно наблюдать среди разных реализаций, а Python re просто выбирает следовать первой строке реализации.

1. Всегда сталкивайтесь с одним символом с совпадением нулевой ширины

. В Java и JavaScript совпадение нулевой ширины заставляет индекс обрываться одним символом, поскольку пребывание в одном и том же индексе приведет к бесконечному циклу в FindAll или ReplaceAll.

В результате вывод операций FindAll в такой реализации может содержать не более 1 совпадения, начиная с определенного индекса.

Пакет Python re по умолчанию, вероятно, также выполните ту же реализацию (и, похоже, это также относится к Ruby).

2. Запретить совпадение нулевой ширины в следующем совпадении с одним и тем же индексом

. В PHP, который предоставляет оболочку поверх libreary PCRE, совпадение нулевой ширины не приводит к тому, что индекс сразу же ударяется. Вместо этого он установит флаг (PCRE_NOTEMPTY), требующий следующего совпадения (которое начинается с того же индекса), чтобы совпадало с нулевой шириной. Если совпадение будет успешным, оно будет совпадать по длине совпадения (отличное от нуля); в противном случае он сталкивается одним символом.

Кстати, библиотека PCRE не обеспечивает встроенную операцию FindAll или ReplaceAll. Фактически это обеспечивается оболочкой PHP.

В результате вывод операций FindAll в такой реализации может содержать до двух совпадений, начинающихся с того же индекса.

Пакет Python regex вероятно, следует этой строке реализации.

Эта линия реализации более сложна, так как она требует, чтобы реализация FindAll или ReplaceAll сохраняла дополнительное состояние, чтобы запретить совпадение нулевой ширины или нет. Разработчику также необходимо отслеживать эти дополнительные флаги, когда они используют API с низким уровнем соответствия.

1
ответ дан Community 15 August 2018 в 22:42
поделиться

Вы уверены, что правильно интерпретировали документацию re.sub ?

*?, +?, ?? «» , '+' и '?' квалификаторы все жадные; они соответствуют как можно большему количеству текста. Иногда такое поведение нежелательно; если RE & lt;. > сопоставляется с '<H1>title</H1>', он будет соответствовать всей строке, а не только '<H1>'. Добавление '?' после того, как квалификатор делает его исполнением в неживой или минимальной форме; как можно меньше символов. С помощью .*? в предыдущем выражении будет соответствовать только ''.

Добавление ? превратит выражение в неживое.

Greedy:

re.sub(".*", "-", "abc")

non-Greedy:

re.sub(".*?", "-", "abc")

Обновление: FWIW re.sub делает именно то, что он должен:

>>> from re import sub
>>> sub(".*?", "-", "abc")
'-a-b-c-'
>>> sub(".*", "-", "abc")
'-'

См. удивительный ответ @ BrenBarn о том, почему вы get -a-b-c-:)

Вот визуальное представление о том, что происходит:

.*?

Regular expression visualization [/g3]

Debuggex Демонстрационный

3
ответ дан James Mills 15 August 2018 в 22:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: