Ваш шаблон немного неправильный. Вам нужно экранировать [
и ]
и не нужно экранировать @
, поскольку @
не является специальным символом в регулярном выражении. Также для захвата содержимого между этими начальным и конечным тегами недостаточно .
, поскольку он будет захватывать только один символ, поэтому вам нужно использовать осмотры вокруг и использовать .+?
для захвата текста между ними не жадным образом. Попробуйте использовать это регулярное выражение,
(?<=\[@introS\]).+?(?=\[@introEnd@\])
Здесь, (?<=\[@introS\])
положительный взгляд позади гарантирует, что любой текст будет захвачен, предшествует в буквальном смысле [@introS]
текст, а затем .+?
захватывает любой один или несколько символов как меньше (?=\[@introEnd@\])
и, по возможности, положительный взгляд на будущее [1111]. ] Редактировать: [1130]
В вашем коде было несколько проблем.
read()
для объекта file
, чтобы извлечь строку из файла findall
вместо сопоставления, когда сопоставление работает по-другому и пытается сопоставить полный текст с регулярным выражением encoding="utf-8"
для чтения / записи файла, поскольку файл содержит символы Юникода. Вот обновленная рабочая копия вашего кода,
import re
def separate_chapters():
pat = re.compile(r'(?<=\[@introS\]).+?(?=\[@introEnd@\])')
with open('text1_scott.txt', 'r', encoding="utf-8") as file:
for i in pat.findall(file.read()):
print(i)
inp = input("write text to a file? Y|N: ")
if inp != "Y":
continue
file_name = input("Name of your file: ")
with open(file_name, "w", encoding="utf-8") as out_file:
out_file.write(i)
print("text {} written to a file".format(i))
separate_chapters()
, которая хорошо выполнила и записала текст главы в имя файла, которое я ввел, когда мне предложили ввести имя файла. Здесь почти 3 часа утра, и я чувствую себя слишком уставшим и засыпаю, поэтому, возможно, не смогу ответить ни на один из дальнейших вопросов сейчас, но, несомненно, утром. И, надеюсь, вам больше не придется сталкиваться с какими-либо проблемами.
Это кажется, что Вы после эквивалента "константы" от C++. Это не существует в C#. Нет никакого способа указать, что потребители не могут изменить свойства объекта, но что-то еще может (предположение, что видоизменяющиеся участники общедоступны, конечно).
Вы могли возвратить клон Нечто, как предложено или возможно представление на Нечто, как ReadOnlyCollection делает для наборов. Конечно, если Вы могли бы сделать Foo
неизменный тип, который сделал бы жизнь более простой...
Обратите внимание, что существует большая разница между созданием поля, только для чтения и созданием самого объекта, неизменного.
В настоящее время сам тип мог изменить вещи обоими способами. Это могло сделать:
_Foo = new Foo(...);
или
_Foo.SomeProperty = newValue;
Если это только должно смочь сделать второе, поле могло бы быть только для чтения, но у Вас все еще есть проблема людей, выбирающих способность свойства видоизменить объект. Если это только должно сделать первое, и на самом деле Foo
или уже неизменно или мог быть сделан неизменным, можно просто обеспечить свойство, которое только имеет "метод считывания", и Вы будете в порядке.
Очень важно, чтобы Вы поняли различие между изменением значения поля (чтобы заставить его относиться к другому экземпляру) и изменение содержания объекта, к которому относится поле.
Если Вы не хотите, чтобы кто-либо смешал с Вашим состоянием... не выставляют его! Как другие сказали, если что-то должно просмотреть Ваше внутреннее состояние, обеспечьте неизменное представление его. С другой стороны, заставьте клиенты говорить Вам делать что-то (Google для "говорят, не спрашивают"), вместо того, чтобы делать его сами.
К сожалению, нет никакого простого способа вокруг этого в C# в данный момент. Вы могли извлечь "часть только для чтения" Foo
в интерфейсе и позволяют Вашему возврату свойства это вместо Foo
.
Делая копию, a ReadOnlyCollection
, или наличие Foo
будьте неизменны, обычно эти три оптимальных маршрута, поскольку Вы уже размышляли.
Я иногда одобряю методы вместо свойств каждый раз, когда я делаю что-либо более значительное, чем простой возврат базового поля, в зависимости от того, сколько работы включено. Методы подразумевают, что что-то продолжается, и повысьте больше флага для потребителей, когда они используют Ваш API.
"Клонирование" Foo возражает, что Вы получаете и отдаете, нормальная практика, названная защитным копированием. Если нет некоторый невидимый побочный эффект к клонированию, которое будет видимо пользователю, нет абсолютно никакой причины НЕ сделать это. Это часто - единственный способ защитить внутренние частные данные Ваших классов, особенно в C# или Java, где идея C++ const
не доступно. (IE, это должно быть сделано для надлежащего создания действительно неизменных объектов на этих двух языках.)
Просто для уточнения возможные побочные эффекты были бы вещами как Ваш пользователь (обоснованно) ожидающий, что исходный объект быть возвращенным, или некоторый ресурс, сохраненный Foo, который не будет клонирован правильно. (В этом случае, что это делает реализацию IClonable?!)
Для разъяснения комментария Jon Skeet, можно сделать представление, которое является неизменным классом обертки для изменяемого Foo. Вот пример:
class Foo{
public string A{get; set;}
public string B{get; set;}
//...
}
class ReadOnlyFoo{
Foo foo;
public string A { get { return foo.A; }}
public string B { get { return foo.B; }}
}
Можно на самом деле воспроизвести поведение константы C++ в C# - просто необходимо сделать это вручную.
Без разницы Foo
единственный способ, которым вызывающая сторона может изменить его состояние, вызывающими методами для него или свойствами установки.
Например, Foo
имеет тип FooClass
:
class FooClass
{
public void MutateMyStateYouBadBoy() { ... }
public string Message
{
get { ... }
set { ... }
}
}
Таким образом в Вашем случае, Вы рады за них добраться Message
свойство, но не набор это, и Вы определенно не довольны ими называющий тот метод.
Поэтому определите интерфейс, описывающий, что им позволяют сделать:
interface IFooConst
{
public string Message
{
get { ... }
}
}
Мы не учли метод видоизменения и только уехали в методе считывания на свойстве.
Затем добавьте что интерфейс к основному списку FooClass
.
Теперь в Вашем классе с Foo
свойство, у Вас есть поле:
private FooClass _foo;
И метод считывания свойства:
public IFooConst Foo
{
get { return _foo; }
}
Это в основном воспроизводит вручную точно что C++ const
ключевое слово сделало бы автоматически. В терминах psuedo-C++, ссылке типа const Foo &
похож на автоматически сгенерированный тип, который только включает тех членов Foo
это было отмечено как const
участники. Переводя это в некоторую теоретическую будущую версию C#, Вы объявили бы FooClass
как это:
class FooClass
{
public void MutateMyStateYouBadBoy() { ... }
public string Message
{
get const { ... }
set { ... }
}
}
Действительно все, что я сделал, объединяется информация в IFooConst
назад в FooClass
, путем меток одного безопасного участника с новым const
ключевое слово. Таким образом в некотором смысле, добавление ключевого слова константы не добавило бы много к языку помимо формального подхода к этому шаблону.
Затем, если у Вас был a const
ссылка на a FooClass
объект:
const FooClass f = GetMeAFooClass();
Вы только смогли бы обратиться к участникам константы f
.
Отметьте это если FooClass
определение общедоступно, вызывающая сторона могла бросить IFooConst
в a FooClass
. Но они могут сделать это в C++ также - он отозван, "бросив const
"и включает названный специальный оператор const_cast<T>(const T &)
.
Существует также проблема интерфейсов, не являющихся очень легким развиться между версиями Вашего продукта. Если третье лицо может реализовать интерфейс, Вы определяете (который они свободны сделать, если они видят его), то Вы не можете добавить новые методы к нему в будущих версиях, не требуя, чтобы другие перекомпилировали их код. Но это - только проблема, если Вы пишете расширяемую библиотеку для других для построения. Возможно, встроенное const
функция решила бы эту проблему.