nprogram’s blog

気ままに、プログラミングのトピックについて書いていきます

C#で、正規表現を使って、一行から複数の文字列を抽出する

C#で、正規表現を使って、一行から複数の文字列を抽出するには、

名前空間System.Text.RegularExpressionsのMatchクラスのMatch.Groupsプロパティを使用して抽出できます。

Match.Groupsプロパティは、正規表現に一致したグループのコレクションを取得するプロパティです(以下、ドキュメント)。

https://msdn.microsoft.com/ja-jp/library/system.text.regularexpressions.match.groups(v=vs.110).aspx

早速、テストコードで試していきたいと思います。 テスト文字列は、OKパターンとNGパターンの二つを用意しました。 テスト文字列のカタカナ文字列を取得するように、正規表現パターンを記載しました。

正規表現の記載の仕方は、以下のサイトがわかりやすいです。 qiita.com

using System;
using System.Text.RegularExpressions;

namespace RegexTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string logOK = "お客様のアカウントのセットアップを完了するには、このメールアドレスがご本人のものであることを確認する必要があります。";
            string logNG = "お客様のアカウントのセットアップを完了するには、このメールアドレスが偽物であることを確認する必要があります。";

            // 正規表現オブジェクトをインスタンス化する
            Regex regex = new Regex("お客様の(.*)の(.*)を完了するには、この(.*)がご本人のものであることを確認する");

            // 正規表現パターンをテキスト文字列と照合する
            Match match =  regex.Match(logOK);

            Console.WriteLine("OKログで、正規表現に一致したグループ個数 : " + match.Groups.Count + "\r\n照合結果 : " + match.Success);

            int i = 0;

            foreach (var item in match.Groups)
            {
                Console.WriteLine("match.Groups[" + i + "] : " + item);
                i++;
            }

            match = regex.Match(logNG);

            Console.WriteLine("\r\nNGログで、正規表現に一致したグループ個数 : " + match.Groups.Count + "\r\n照合結果 : " + match.Success);

            i = 0;

            foreach (var item in match.Groups)
            {
                Console.WriteLine("match.Groups[" + i + "] : " + item);
                i++;
            }

            Console.ReadLine();
        }
    }
}

[テストプログラム実行結果] f:id:nprogram:20171206074801p:plain

OKパターンの場合は、照合結果[Match.Successプロパティの値]がTrueとなりますが、

NGパターンでは、照合結果[Match.Successプロパティの値]がFalseとなります。

OKパターンのテスト結果を見てわかるように、コレクションの最初の要素は、照合した文字列自体が格納されます。

その後は、照合した順番で、文字列が格納されます。

C# オブジェクト指向設計の学習

  • メソッドでパラメータを渡すのではなく、オブジェクト生成時に必要なデータをすべて準備する
  • データと、そのデータを使うロジックは、一つのクラスにまとめる
  • 一つ一つのオブジェクトの役割は単純にする
  • 複雑な処理は、オブジェクトを組み合わせて実現する

C# シングルトンパターンの学習

C#で簡単なシングルトンパターンを記載してみます。

using System;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {

            SingletonClass instance = SingletonClass.Instance;
            SingletonClass instance2 = SingletonClass.Instance;

            if (instance == instance2)
            {
                Console.WriteLine("instance == instance2");
            }

            instance.DoSomething();
            instance2.DoSomething();

            Console.ReadLine();
        }
    }

    public sealed class SingletonClass
    {
        private static SingletonClass m_Instance;

        private SingletonClass()
        {
            Console.WriteLine("Created instance.");
        }

        public static SingletonClass Instance
        {
            get
            {
                if (m_Instance == null)
                {
                    m_Instance = new SingletonClass();
                }

                return m_Instance;
            }
        }

        public void DoSomething()
        {
            Console.WriteLine("DoSomething is called.");
        }
    }
}

実行結果

f:id:nprogram:20171009223243p:plain

C#でファイルから一行ずつ読み出し、正規表現を使って文字列を検索し、抽出する

C#で、ファイルから一行ずつ読み出し、文字列を検索し、抽出する方法はいくつかありますが、正規表現を使う方法が一般的です。

以下に、ファイルから一行ずつ読み出し、正規表現を使って文字列を検索し、抽出するプログラムを記載します。

D:\test.txtに以下のようなファイルがある場合において、1行ずつ文字列を読み出します。読み出す処理は、最終行まで繰り返し実施します。 正規表現パターンrgxが、読みだした文字列に存在するかどうか、Matchオブジェクトの Successプロパティの値を確認して判断します。 一致が見つかった場合、返された Match オブジェクトの Value プロパティから部分文字列が含まれています。 一致が検出されない場合、値は String.Emptyです。

test1
test2
test3
test4
test5
using System;
using System.Text.RegularExpressions;

namespace LogRead
{
    class Program
    {
        static void Main(string[] args)
        {
            // Instantiate the regular expression object.
            Regex rgx = new Regex(@"test3", RegexOptions.IgnoreCase);

            using (System.IO.StreamReader file = new System.IO.StreamReader(@"D:\test.txt", System.Text.Encoding.ASCII))
            {
                string line = "";

                while ((line = file.ReadLine()) != null)
                {
                    if (rgx.Match(line).Success)
                    {
                        Console.WriteLine(line);
                        System.Diagnostics.Debug.WriteLine(line);
                    }
                }
            }

            System.Console.ReadLine();
        }
    }
}

ただし、上記の場合では、例えば、ファイルが見つからない場合は、例外が発生してしまいます。 f:id:nprogram:20171003233520p:plain

そのような場合は、try catch節を用いるとよいでしょう。

using System;
using System.Text.RegularExpressions;

namespace LogRead
{
    class Program
    {
        static void Main(string[] args)
        {
            // Instantiate the regular expression object.
            Regex rgx = new Regex(@"test3", RegexOptions.IgnoreCase);

            try
            {
                using (System.IO.StreamReader file = new System.IO.StreamReader(@"D:\test.tst", System.Text.Encoding.ASCII))
                {
                    string line = "";

                    while ((line = file.ReadLine()) != null)
                    {
                        if (rgx.Match(line).Success)
                        {
                            Console.WriteLine(line);
                            System.Diagnostics.Debug.WriteLine(line);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // Let the user know what went wrong.
                Console.WriteLine("The file could not be read:");
                Console.WriteLine(e.Message);
            }

            System.Console.ReadLine();
        }
    }
}

以下のように、エラー内容を取得することができました。

f:id:nprogram:20171003235219p:plain

環境について

  • IDE : Microsoft Visual Studio Community 2017
  • プロジェクト : C# コンソールアプリケーション

WPF MVVM基礎の学習

INotifyPropertyChangedインタフェースは、プロパティ値が変更されたことをクライアントに通知するインタフェースです。 ICommandインタフェースは、コマンドを定義するインタフェースです。 操作を実行するためにのExecuteメソッド、操作が実行可能かどうかを返すCanExecuteメソッド、CanExecuteの結果が変化したことを通知するCanExecuteChangedイベントを公開します。

MVVMの構造パターン

f:id:nprogram:20170918140725p:plain

ビューは、自身をデータバインディングターゲットとして、データバインディングを確立するとき、INotifyPropertyChangedを実装したオブジェクトをバインディングソースにすることで、 ソースプロパティの変更を検知できます。

ビューはICommandをボタンやその他のアクションとバインドすることで、アクション可能かどうか判断しつつ、ロジックを呼び出すことができます。

INotifyPropertyChangedやICommandは、ビューの上記の仕様を満たすために、用意されています。

MVVMを考慮した簡単なWPFアプリケーションのサンプルは以下のサイトが非常にお勧めです。

<参考サイト>

garafu.blogspot.jp