Знайти і замінити

Ви можете легко переміщатися по документу за допомогою клавіатури та миші, але якщо вам потрібно прокрутити багато сторінок, Пошук певного тексту в довгому документі займе досить багато часу. Якщо ви хочете замінити певні символи або слова, які ви використовували в документі, це займе більше часу. Функція “Знайти та замінити” дозволяє знайти послідовність символів у документі та замінити її іншою послідовністю символів.

Aspose.Words дозволяє знайти в документі певний рядок або шаблон регулярного виразу і замінити його альтернативним варіантом без установки і використання додаткових додатків, таких як Microsoft Word. Це пришвидшить виконання багатьох завдань набору тексту та форматування, що потенційно заощадить вам години роботи.

У цій статті пояснюється, як застосовувати заміну рядків та регулярні вирази з підтримкою метасимволів.

Способи пошуку і заміни

Aspose.Words надає два способи застосувати операцію пошуку та заміни, використовуючи наступне:

  1. Simple string replacement – щоб знайти та замінити певний рядок на інший, вам потрібно вказати рядок пошуку (буквено-цифрові символи), який буде замінено відповідно до всіх появ іншим зазначеним рядком заміни. Обидва рядки не повинні містити символів. Візьміть до уваги, що порівняння рядків може бути чутливим до регістру, або ви можете бути не впевнені в правильності написання, або у вас може бути кілька подібних варіантів написання.
  2. Regular expressions – щоб задати регулярний вираз для пошуку точних збігів рядків і заміни їх відповідно до вашим регулярним виразом. Зверніть увагу, що слово визначається як таке, що складається лише з буквено-цифрових символів. Якщо при заміні збігаються тільки цілі слова, а вхідний рядок містить Символи, то фрази знайдені не будуть.

Крім того, ви можете використовувати спеціальні метасимволи з простою заміною рядків і регулярні вирази для вказівки розривів в рамках операції пошуку і заміни.

Aspose.Words представляє функціональність пошуку та заміни в просторі імен Aspose.Words.Replacing. У процесі пошуку та заміни ви можете працювати з багатьма параметрами, використовуючи клас FindReplaceOptions.

Знайдіть і замініть текст за допомогою простої заміни рядка

Ви можете використовувати один із методів Replace, щоб знайти або замінити певний рядок і повернути кількість виконаних замін. У цьому випадку ви можете вказати рядок, який потрібно замінити, рядок, який замінить усі його випадки, чи буде Заміна чутливою до регістру та чи будуть порушені лише окремі слова.

Наступний приклад коду показує, як знайти рядок “CustomerName " і замінити його рядком “James Bond”:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
// Load a Word Docx document by creating an instance of the Document class.
auto doc = System::MakeObject<Document>();
auto builder = System::MakeObject<DocumentBuilder>(doc);
builder->Writeln(u"Hello _CustomerName_, ");
// Specify the search string and replace string using the Replace method.
doc->get_Range()->Replace(u"_CustomerName_", u"James Bond", System::MakeObject<FindReplaceOptions>());
// Save the result.
System::String outputPath = outputDataDir + u"Range.ReplaceSimple.docx";
doc->Save(outputPath);

Ви можете помітити різницю між документами, перш ніж застосовувати просту заміну рядків:

before-simple-string-replacement-aspose-words-cpp

І після застосування простої заміни рядка:

after-simple-string-replacement-aspose-words-cpp

Пошук і заміна тексту за допомогою регулярних виразів

Регулярний вираз (regex) - це шаблон, який описує певну послідовність тексту. Припустимо, ви хочете замінити всі подвійні входження слова одним входженням слова. Потім ви можете застосувати наступний регулярний вираз, щоб вказати шаблон із двох слів: ([a-zA-Z]+) \1.

Використовуйте інший метод Replace для пошуку та заміни певних комбінацій символів, встановивши параметр Regex Як шаблон регулярного виразу для пошуку збігів.

Наступний приклад коду показує, як замінити рядки, що відповідають шаблону регулярного виразу, вказаному рядком заміни:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
System::SharedPtr<Document> doc = System::MakeObject<Document>();
auto builder = System::MakeObject<DocumentBuilder>(doc);
builder->Writeln(u"sad mad bad");
System::SharedPtr<FindReplaceOptions> options = System::MakeObject<FindReplaceOptions>();
// Replaces all occurrences of the words "sad" or "mad" to "bad".
doc->get_Range()->Replace(System::MakeObject<System::Text::RegularExpressions::Regex>(u"[s|m]ad"), u"bad", options);
const System::String outputPath = outputDataDir + u"FindAndReplaceWithRegex_out.doc";
doc->Save(outputPath);

Ви можете помітити різницю між документами, перш ніж застосовувати заміну рядків регулярними виразами:

before-replacement-with-regular-expressions-aspose-words-cpp

І після застосування заміни рядків регулярними виразами:

after-replacement-with-regular-expressions-aspose-words-cpp

Знайдіть і замініть рядок за допомогою метасимволів

Ви можете використовувати метасимволи в рядку пошуку або в рядку заміни, якщо певний текст або фраза складається з декількох абзаців, розділів або сторінок. Деякі з метасимволів включають &p для позначення розриву абзацу, &b для позначення розриву розділу, &m для позначення розриву сторінки та &l для позначення розриву рядка.

Наступний приклад коду показує, як замінити текст абзацом та розривом сторінки:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
System::SharedPtr<Document> doc = System::MakeObject<Document>();
System::SharedPtr<DocumentBuilder> builder = System::MakeObject<DocumentBuilder>(doc);
builder->get_Font()->set_Name(u"Arial");
builder->Writeln(u"First section");
builder->Writeln(u" 1st paragraph");
builder->Writeln(u" 2nd paragraph");
builder->Writeln(u"{insert-section}");
builder->Writeln(u"Second section");
builder->Writeln(u" 1st paragraph");
System::SharedPtr<FindReplaceOptions> options = System::MakeObject<FindReplaceOptions>();
options->get_ApplyParagraphFormat()->set_Alignment(ParagraphAlignment::Center);
// Double each paragraph break after word "section", add kind of underline and make it centered.
int32_t count = doc->get_Range()->Replace(u"section&p", u"section&p----------------------&p", options);
// Insert section break instead of custom text tag.
count = doc->get_Range()->Replace(u"{insert-section}", u"&b", options);
System::String savePath = outputDataDir + u"FindReplaceUsingMetaCharacters.ReplaceTextContaingMetaCharacters.docx";
doc->Save(savePath);

Ви можете знайти та замінити текст у верхньому/нижньому колонтитулі документа Word за допомогою класу HeaderFooter.

Наступний зразок коду показує, як замінити текст розділу заголовка у вашому документі:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
// Open the template document, containing obsolete copyright information in the footer.
auto doc = System::MakeObject<Document>(inputDataDir + u"HeaderFooter.ReplaceText.doc");
// Access header of the Word document.
auto headersFooters = doc->get_FirstSection()->get_HeadersFooters();
auto header = headersFooters->idx_get(HeaderFooterType::HeaderPrimary);
// Set options.
auto options = System::MakeObject<FindReplaceOptions>();
options->set_MatchCase(false);
options->set_FindWholeWordsOnly(false);
// Replace text in the header of the Word document.
header->get_Range()->Replace(u"Aspose.Words", u"Remove", options);
auto footer = headersFooters->idx_get(HeaderFooterType::FooterPrimary);
footer->get_Range()->Replace(u"(C) 2006 Aspose Pty Ltd.", u"Copyright (C) Aspose Pty Ltd.", options);
// Save the Word document.
doc->Save(outputDataDir + u"HeaderReplace.docx");

Ви можете помітити різницю між документами до застосування заміни рядка заголовка:

before-applying-header-string-replacement-aspose-words-cpp

І після застосування заміни рядка заголовка:

after-applying-header-string-replacement-aspose-words-cpp

Приклад коду для заміни тексту нижнього колонтитула у вашому документі дуже схожий на попередній приклад коду верхнього колонтитула. Все, що вам потрібно зробити, це замінити наступні два рядки:

auto header = headersFooters->idx_get(HeaderFooterType::HeaderPrimary);
header->get_Range()->Replace(u"Aspose.Words", u"Remove", options);

З наступним:

auto footer = headersFooters->idx_get(HeaderFooterType::FooterPrimary);
footer->get_Range()->Replace(u"(C) 2006 Aspose Pty Ltd.", u"Copyright (C) Aspose Pty Ltd.", options);

Ви можете помітити різницю між документами, перш ніж застосувати заміну рядка нижнього колонтитула:

before-applying-footer-string-replacement-aspose-words-cpp

І після застосування заміни рядка нижнього колонтитула:

after-applying-footer-string-replacement-aspose-words-cpp

Ігнорувати текст під час пошуку та заміни

Застосовуючи операцію пошуку та заміни, ви можете ігнорувати певні фрагменти тексту. Таким чином, певні частини тексту можуть бути виключені з пошуку, а пошук та заміна можуть бути застосовані лише до решти частин.

Aspose.Words надає багато властивостей пошуку та заміни для ігнорування тексту, таких як IgnoreDeleted, IgnoreFieldCodes, IgnoreFields, IgnoreFootnotes, і IgnoreInserted.

Наступний приклад коду показує, як ігнорувати текст всередині змін видалення:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
System::SharedPtr<Document> doc = System::MakeObject<Document>();
System::SharedPtr<DocumentBuilder> builder = System::MakeObject<DocumentBuilder>(doc);
// Insert non-revised text.
builder->Writeln(u"Deleted");
builder->Write(u"Text");
// Remove first paragraph with tracking revisions.
doc->StartTrackRevisions(u"John Doe", System::DateTime::get_Now());
doc->get_FirstSection()->get_Body()->get_FirstParagraph()->Remove();
doc->StopTrackRevisions();
System::SharedPtr<FindReplaceOptions> options = System::MakeObject<FindReplaceOptions>();
// Replace 'e' in document while deleted text.
options->set_IgnoreDeleted(true);
doc->get_Range()->Replace(System::MakeObject<Regex>(u"e"), u"*", options);
std::cout << doc->GetText().ToUtf8String() << std::endl; // The output is: Deleted\rT*xt\f
// Replace 'e' in document NOT ignoring deleted text.
options->set_IgnoreDeleted(false);
doc->get_Range()->Replace(System::MakeObject<Regex>(u"e"), u"*", options);
std::cout << doc->GetText().ToUtf8String() << std::endl; // The output is: D*l*t*d\rT*xt\f

Налаштування операції пошуку та заміни

Aspose.Words надає безліч різних properties способів пошуку та заміни тексту, таких як застосування певного формату з властивостями ApplyFont та ApplyParagraphFormats, використання підстановок у шаблонах заміни з властивістю UseSubstitutions та інші.

Наступний приклад коду показує, як виділити певне слово у вашому документі:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
// Highlight word "the" with yellow color.
auto options = System::MakeObject<FindReplaceOptions>();
options->get_ApplyFont()->set_HighlightColor(System::Drawing::Color::get_Yellow());
// Replace highlighted text.
doc->get_Range()->Replace(u"Hello", u"Hello", options);

Aspose.Words дозволяє використовувати інтерфейс IReplacingCallback для створення та виклику користувацького методу під час операції заміни. У вас можуть бути деякі випадки використання, коли Вам потрібно налаштувати операцію пошуку та заміни, наприклад, замінити текст, вказаний у регулярному виразі, тегами HTML, тому в основному ви будете застосовувати заміну за допомогою вставки HTML.

Якщо вам потрібно замінити рядок тегом HTML, застосуйте інтерфейс IReplacingCallback, щоб налаштувати операцію пошуку та заміни таким чином, щоб зіставлення починалося на початку виконання з вузла зіставлення вашого документа. Наведемо кілька прикладів використання IReplacingCallback.

Наступний приклад коду показує, як замінити текст, вказаний на HTML:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
class ReplaceWithHtmlEvaluator : public IReplacingCallback
{
typedef ReplaceWithHtmlEvaluator ThisType;
typedef IReplacingCallback BaseType;
typedef ::System::BaseTypesInfo<BaseType> ThisTypeBaseTypesInfo;
RTTI_INFO(ThisType, ThisTypeBaseTypesInfo);
public:
ReplaceWithHtmlEvaluator(System::SharedPtr<FindReplaceOptions> options);
ReplaceAction Replacing(System::SharedPtr<ReplacingArgs> args) override;
private:
System::SharedPtr<FindReplaceOptions> mOptions;
};
ReplaceWithHtmlEvaluator::ReplaceWithHtmlEvaluator(System::SharedPtr<FindReplaceOptions> options)
{
mOptions = options;
}
ReplaceAction ReplaceWithHtmlEvaluator::Replacing(System::SharedPtr<ReplacingArgs> args)
{
System::SharedPtr<DocumentBuilder> builder = System::MakeObject<DocumentBuilder>(System::DynamicCast<Document>(args->get_MatchNode()->get_Document()));
builder->MoveTo(args->get_MatchNode());
// Replace '<CustomerName>' text with a red bold name.
builder->InsertHtml(u"<b><font color='red'>James Bond, </font></b>");
args->set_Replacement(u"");
return ReplaceAction::Replace;
}
void ReplaceWithHtml(System::String const& inputDataDir, System::String const& outputDataDir)
{
auto doc = System::MakeObject<Document>();
auto builder = System::MakeObject<DocumentBuilder>(doc);
builder->Writeln(u"Hello <CustomerName>,");
auto options = System::MakeObject<FindReplaceOptions>();
auto optionsReplacingCallback = System::MakeObject<ReplaceWithHtmlEvaluator>(options);
doc->get_Range()->Replace(new Regex(u" <CustomerName>,"), System::String::Empty, options);
// Save the modified document.
doc->Save(outputDataDir + u"Range.ReplaceWithInsertHtml.doc");
}

У наступному прикладі коду показано, як виділити позитивні числа зеленим кольором, а негативні-червоним:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
// Replace and Highlight Numbers.
class NumberHighlightCallback : public IReplacingCallback
{
typedef NumberHighlightCallback ThisType;
typedef IReplacingCallback BaseType;
typedef ::System::BaseTypesInfo<BaseType> ThisTypeBaseTypesInfo;
RTTI_INFO(ThisType, ThisTypeBaseTypesInfo);
public:
NumberHighlightCallback(System::SharedPtr<FindReplaceOptions> const& opt)
: mOpt(opt) { }
Aspose::Words::Replacing::ReplaceAction Replacing(System::SharedPtr<Aspose::Words::Replacing::ReplacingArgs> args) override
{
// Let replacement to be the same text.
args->set_Replacement(args->get_Match()->get_Value());
auto val = System::Convert::ToInt32(args->get_Match()->get_Value());
// Apply either red or green color depending on the number value sign.
mOpt->get_ApplyFont()->set_Color(val > 0 ? System::Drawing::Color::get_Green() : System::Drawing::Color::get_Red());
return ReplaceAction::Replace;
}
private:
System::SharedPtr<FindReplaceOptions> mOpt;
};

Наступний приклад коду показує, як додати номер рядка перед кожним рядком:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
class LineCounterCallback : public IReplacingCallback
{
typedef LineCounterCallback ThisType;
typedef IReplacingCallback BaseType;
typedef ::System::BaseTypesInfo<BaseType> ThisTypeBaseTypesInfo;
RTTI_INFO(ThisType, ThisTypeBaseTypesInfo);
public:
Aspose::Words::Replacing::ReplaceAction Replacing(System::SharedPtr<Aspose::Words::Replacing::ReplacingArgs> args) override
{
std::cout << args->get_Match()->get_Value().ToUtf8String() << '\n';
args->set_Replacement(System::String::Format(u"{0} {1}", mCounter++, args->get_Match()->get_Value()));
return ReplaceAction::Replace;
}
private:
int32_t mCounter = 1;
};
void LineCounter(System::String const& inputDataDir, System::String const& outputDataDir)
{
// Create a document.
auto doc = System::MakeObject<Document>();
auto builder = System::MakeObject<DocumentBuilder>(doc);
// Add lines of text.
builder->Writeln(u"This is first line");
builder->Writeln(u"Second line");
builder->Writeln(u"And last line");
// Prepend each line with line number.
auto opt = System::MakeObject<FindReplaceOptions>();
opt->set_ReplacingCallback(System::MakeObject<LineCounterCallback>());
doc->get_Range()->Replace(System::MakeObject<Regex>(u"[^&p]*&p"), u"", opt);
doc->Save(outputDataDir + u"TestLineCounter.docx");
}