検索と置換

キーボードとマウスを使用して文書内を簡単に移動できますが、スクロールするページが多い場合、長い文書内で特定のテキストを見つけるのにかなりの時間がかかります。文書内で使用した特定の文字や単語を置き換える場合は、さらに時間がかかります。 「検索と置換」機能を使用すると、文書内で一連の文字を検索し、別の一連の文字に置き換えることができます。

Aspose.Words を使用すると、Microsoft Word などの追加のアプリケーションをインストールして使用しなくても、ドキュメント内で特定の文字列または正規表現パターンを検索し、代替文字列に置き換えることができます。これにより、多くの入力や書式設定のタスクが高速化され、作業時間を節約できる可能性があります。

この記事では、メタキャラクターのサポートを使用して文字列置換と正規表現を適用する方法について説明します。

{#ways-to-find-and-replace} を検索して置換する方法

Aspose.Words では、次の 2 つの方法で検索と置換操作を適用できます。

  1. 単純な文字列置換 – 特定の文字列を検索して別の文字列に置換するには、すべての出現に従って別の指定された置換文字列に置換される検索文字列 (英数字) を指定する必要があります。どちらの文字列にも記号を含めることはできません。文字列の比較では大文字と小文字が区別される場合があること、またはスペルがわからない場合や、類似したスペルが複数ある場合があることを考慮してください。
  2. 正規表現 – 正規表現を指定して、完全に一致する文字列を検索し、正規表現に従って置換します。単語は英数字のみで構成されるものとして定義されることに注意してください。単語全体のみが一致する置換が実行され、入力文字列にたまたま記号が含まれている場合、フレーズは検出されません。

さらに、単純な文字列置換および正規表現とともに特別なメタキャラクタを使用して、検索および置換操作内でブレークを指定できます。

Aspose.Words は、Aspose.Words.Replacing 名前空間を使用して検索と置換の機能を提供します。 FindReplaceOptions クラスを使用して、検索と置換のプロセス中に多くのオプションを使用できます。

単純な文字列置換 {#find-and-replace-text-using-simple-string-replacement} を使用したテキストの検索と置換

Replace メソッドの 1 つを使用して、特定の文字列を検索または置換し、行われた置換の数を返すことができます。この場合、置換する文字列、その出現箇所すべてを置換する文字列、置換で大文字と小文字を区別するかどうか、および単独の単語のみが影響を受けるかどうかを指定できます。

次のコード例は、文字列「CustomerName」を検索し、文字列 「James Bond」 に置き換える方法を示しています。

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

単純な文字列置換を適用する前に、ドキュメントの違いに気づくことができます。

単純な文字列置換前

単純な文字列置換を適用した後:

単純な文字列置換後

正規表現を使用したテキストの検索と置換

正規表現 (regex) は、特定のテキストのシーケンスを記述するパターンです。単語が 2 回出現するすべての単語を 1 つの単語に置き換えるとします。次に、正規表現 ([a-zA-Z]+) \1 を適用して、ダブルワード パターンを指定できます。

もう 1 つの Replace メソッドを使用して、一致を見つけるための正規表現パターンとして Regex パラメータを設定し、特定の文字の組み合わせを検索および置換します。

次のコード例は、正規表現パターンに一致する文字列を指定された置換文字列で置換する方法を示しています。

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET
Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
builder.Writeln("sad mad bad");
Assert.AreEqual("sad mad bad", doc.GetText().Trim());
// Replaces all occurrences of the words "sad" or "mad" to "bad".
doc.Range.Replace(new Regex("[s|m]ad"), "bad");
// Save the Word document.
doc.Save("Range.ReplaceWithRegex.docx");

正規表現による文字列置換を適用する前に、ドキュメントの違いに気づくことができます。

正規表現による置換前

そして、正規表現による文字列置換を適用した後、次のようになります。

正規表現による置換後

メタキャラクターを使用した文字列の検索と置換

特定のテキストまたは語句が複数の段落、セクション、またはページで構成されている場合は、検索文字列または置換文字列でメタキャラクターを使用できます。メタキャラクタの中には、段落区切りの &p、セクション区切りの &b、ページ区切りの &m、改行の &l などがあります。

次のコード例は、テキストを段落と改ページに置き換える方法を示しています。

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET
Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
builder.Font.Name = "Arial";
builder.Writeln("First section");
builder.Writeln(" 1st paragraph");
builder.Writeln(" 2nd paragraph");
builder.Writeln("{insert-section}");
builder.Writeln("Second section");
builder.Writeln(" 1st paragraph");
FindReplaceOptions options = new FindReplaceOptions();
options.ApplyParagraphFormat.Alignment = ParagraphAlignment.Center;
// Double each paragraph break after word "section", add kind of underline and make it centered.
int count = doc.Range.Replace("section&p", "section&p----------------------&p", options);
// Insert section break instead of custom text tag.
count = doc.Range.Replace("{insert-section}", "&b", options);
dataDir = dataDir + "ReplaceTextContaingMetaCharacters_out.docx";
doc.Save(dataDir);

HeaderFooter クラスを使用すると、Word 文書のヘッダー/フッター セクション内のテキストを検索して置換できます。

次のコード例は、ドキュメント内のヘッダー セクションのテキストを置換する方法を示しています。

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET
// Open the template document, containing obsolete copyright information in the footer.
Document doc = new Document(dataDir + "HeaderFooter.ReplaceText.doc");
// Access header of the Word document.
HeaderFooterCollection headersFooters = doc.FirstSection.HeadersFooters;
HeaderFooter header = headersFooters[HeaderFooterType.HeaderPrimary];
// Set options.
FindReplaceOptions options = new FindReplaceOptions
{
MatchCase = false,
FindWholeWordsOnly = false
};
// Replace text in the header of the Word document.
header.Range.Replace("Aspose.Words", "Remove", options);
// Save the Word document.
doc.Save(dataDir + "HeaderReplace.docx");

ヘッダー文字列の置換を適用する前に、ドキュメントの違いに気づくことができます。

適用前ヘッダー文字列置換

ヘッダー文字列の置換を適用した後:

適用後のヘッダー文字列の置換

ドキュメント内のフッター セクションのテキストを置換するコード例は、前のヘッダー コード例とよく似ています。次の 2 行を置き換えるだけです。

HeaderFooter header = headersFooters[HeaderFooterType.HeaderPrimary];
header.Range.Replace("Aspose.Words", "Remove", options);

以下のとおりです。

HeaderFooter footer = headersFooters[HeaderFooterType.FooterPrimary];
int currentYear = System.DateTime.Now.Year;
footer.Range.Replace("(C) 2006 Aspose Pty Ltd.", $"Copyright (C) {currentYear} by Aspose Pty Ltd.", options);

フッター文字列の置換を適用する前に、ドキュメントの違いに気づくことができます。

適用前フッター文字列置換

フッター文字列置換を適用した後:

適用後のフッター文字列置換

{#ignore-text-during-find-and-replace} の検索と置換中にテキストを無視する

検索と置換操作を適用する際、テキストの特定のセグメントを無視できます。したがって、テキストの特定の部分を検索から除外し、残りの部分にのみ検索と置換を適用することができます。

Aspose.Words には、IgnoreDeletedIgnoreFieldCodesIgnoreFieldsIgnoreFootnotesIgnoreInserted などのテキストを無視するための検索および置換プロパティが多数用意されています。

次のコード例は、削除リビジョン内のテキストを無視する方法を示しています。

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET
Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
// Insert non-revised text.
builder.Writeln("Deleted");
builder.Write("Text");
// Remove first paragraph with tracking revisions.
doc.StartTrackRevisions("John Doe", DateTime.Now);
doc.FirstSection.Body.FirstParagraph.Remove();
doc.StopTrackRevisions();
Regex regex = new Regex("e");
FindReplaceOptions options = new FindReplaceOptions();
// Replace 'e' in document while ignoring deleted text.
options.IgnoreDeleted = true;
doc.Range.Replace(regex, "*", options);
Assert.AreEqual(doc.GetText().Trim(), "Deleted\rT*xt");
// Replace 'e' in document while not ignoring deleted text.
options.IgnoreDeleted = false;
doc.Range.Replace(regex, "*", options);

検索と置換操作 {#customize-find-and-replace-operation} をカスタマイズする

Aspose.Words は、ApplyFont および ApplyParagraphFormats プロパティで特定の形式を適用したり、UseSubstitutions プロパティで置換パターンで置換を使用したりするなど、テキストを検索および置換するためのさまざまな properties を提供します。

次のコード例は、文書内の特定の単語を強調表示する方法を示しています。

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET
// Highlight word "the" with yellow color.
FindReplaceOptions options = new FindReplaceOptions();
options.ApplyFont.HighlightColor = Color.Yellow;
// Replace highlighted text.
doc.Range.Replace("Hello", "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-.NET
public static void ReplaceWithHtml(string dataDir)
{
Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
builder.Writeln("Hello <CustomerName>,");
FindReplaceOptions options = new FindReplaceOptions();
options.ReplacingCallback = new ReplaceWithHtmlEvaluator(options);
doc.Range.Replace(new Regex(@" <CustomerName>,"), String.Empty, options);
// Save the modified document.
doc.Save(dataDir + "Range.ReplaceWithInsertHtml.doc");
}
private class ReplaceWithHtmlEvaluator : IReplacingCallback
{
internal ReplaceWithHtmlEvaluator(FindReplaceOptions options)
{
mOptions = options;
}
//This simplistic method will only work well when the match starts at the beginning of a run.
ReplaceAction IReplacingCallback.Replacing(ReplacingArgs args)
{
DocumentBuilder builder = new DocumentBuilder((Document)args.MatchNode.Document);
builder.MoveTo(args.MatchNode);
// Replace '<CustomerName>' text with a red bold name.
builder.InsertHtml("<b><font color='red'>James Bond, </font></b>"); args.Replacement = "";
return ReplaceAction.Replace;
}
private readonly FindReplaceOptions mOptions;
}

次のコード例は、正の数値を緑色で強調表示し、負の数値を赤色で強調表示する方法を示しています。

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET
// Replace and Highlight Numbers.
internal class NumberHighlightCallback : IReplacingCallback
{
public NumberHighlightCallback(FindReplaceOptions opt)
{
mOpt = opt;
}
public ReplaceAction Replacing(ReplacingArgs args)
{
// Let replacement to be the same text.
args.Replacement = args.Match.Value;
int val = int.Parse(args.Match.Value);
// Apply either red or green color depending on the number value sign.
mOpt.ApplyFont.Color = (val > 0)
? Color.Green
: Color.Red;
return ReplaceAction.Replace;
}
private readonly FindReplaceOptions mOpt;
}

次のコード例は、各行の先頭に行番号を追加する方法を示しています。

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET
public void LineCounter()
{
// Create a document.
Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
// Add lines of text.
builder.Writeln("This is first line");
builder.Writeln("Second line");
builder.Writeln("And last line");
// Prepend each line with line number.
FindReplaceOptions opt = new FindReplaceOptions() { ReplacingCallback = new LineCounterCallback() };
doc.Range.Replace(new Regex("[^&p]*&p"), "", opt);
doc.Save(@"X:\TestLineCounter.docx");
}
internal class LineCounterCallback : IReplacingCallback
{
public ReplaceAction Replacing(ReplacingArgs args)
{
Debug.WriteLine(args.Match.Value);
args.Replacement = string.Format("{0} {1}", mCounter++, args.Match.Value);
return ReplaceAction.Replace;
}
private int mCounter = 1;
}