3

次の形式のファイルを解析しようとしています。

BEGIN:VEVENT
CREATED:20120504T163940Z
DTEND;TZID=America/Chicago:20120504T130000
DTSTAMP:20120504T164000Z
DTSTART;TZID=America/Chicago:20120504T120000
LAST-MODIFIED:20120504T163940Z
SEQUENCE:0
SUMMARY:Test 1
TRANSP:OPAQUE
UID:21F61281-FB76-467F-A2CC-A666688BD9B5
X-RADICALE-NAME:21F61281-FB76-467F-A2CC-A666688BD9B5.ics
END:VEVENT

各行のコロンまたはセミコロンの後にある値を取得し、それらをオブジェクトの小道具に入れる必要があります。私は正規表現でこれを行おうとしていますが、基本的に、正規表現を使用した後は、正規表現について知っていることをすべて忘れています (おそらく年に 2 回)。どんな助けでも大歓迎です。

4

5 に答える 5

6

編集

この投稿で、iCal 形式について考えるようになりました。

昨日まで、私は iCal 形式が何であるかを知りませんでした。しかし、1998年の仕様を読んだ後、このページの回答のどれもコンテンツを解析するのに十分でないことは痛々しいほど明らかです. そして、以下の私の一般的な正規表現でさえ、本当に洗練されすぎています。

それを念頭に置いて、一般的な行コンテンツ解析の仕様から収集されたように、行コンテンツのみを解析するソリューションを次に示します。それは正しい方向への一歩であり、うまくいけば誰かが利益を得ることができます. 行の継続は行わず、検証も行いません。

C# コード

Regex iCalMainRx = new Regex(
 @" ^  (?<name> [^[:cntrl:]"";:,\n]+ )
       (?<parameter>
          ;
          (?<param_name> [^[:cntrl:]"";:,\n]+ )
           = 
          (?<param_value> 
             (?: (?:[^\S\n]|[^[:cntrl:]"";:,])*  | "" (?:[^\S\n]|[^[:cntrl:]""])* "" )
             (?: , (?: (?:[^\S\n]|[^[:cntrl:]"";:,])*  | "" (?:[^\S\n]|[^[:cntrl:]""])* "" ) )*
          )
        )*
        :
        (?<value> (?:[^\S\n]|[^[:cntrl:]])* )
     $ ", RegexOptions.IgnorePatternWhitespace);

Regex iCalPvalRx = new Regex(
 @" ^ (?<pvals> (?:[^\S\n]|[^[:cntrl:]"";:,])*  | "" (?:[^\S\n]|[^[:cntrl:]""])* "" )
      (?: ,+ (?<pvals> (?:[^\S\n]|[^[:cntrl:]"";:,])*  | "" (?:[^\S\n]|[^[:cntrl:]""])* "" ) )*
    $ ", RegexOptions.IgnorePatternWhitespace);


string[] lines = {
    "BEGIN:VEVENT", 
    "CREATED:20120504T163940Z", 
    "DTEND;TZID=America/Chicago:20120504T130000", 
    "DTSTAMP:20120504T164000Z", 
    "DTSTART;TZID=,,,America/Chicago;Next=;last=\"this:;;;:=\";final=:20120504T120000", 
    "LAST-MODIFIED:20120504T163940Z", 
    "SEQUENCE:0", 
    "SUMMARY:Test 1", 
    "TRANSP:OPAQUE", 
    "UID:21F61281-FB76-467F-A2CC-A666688BD9B5", 
    "X-RADICALE-NAME:21F61281-FB76-467F-A2CC-A666688BD9B5.ics", 
    "END:VEVENT", 
};

foreach (string str in lines)
{
    Match m_content = iCalMainRx.Match( str );
    if (m_content.Success)
    {
        Console.WriteLine("Key =   " + m_content.Groups["name"].Value);
        Console.WriteLine("Value = " + m_content.Groups["value"].Value);

        CaptureCollection cc_pname  = m_content.Groups["param_name"].Captures;
        CaptureCollection cc_pvalue = m_content.Groups["param_value"].Captures;
        if (cc_pname.Count > 0)
        {
            Console.WriteLine("Parameters: ");
            for (int i = 0; i < cc_pname.Count; i++)
            {
                // Console.WriteLine("\t'" + cc_pname[i].Value + "'  =   '" + cc_pvalue[i].Value + "'");
                Console.WriteLine("\t'" + cc_pname[i].Value + "' =");
                Match m_vals = iCalPvalRx.Match( cc_pvalue[i].Value );
                if (m_vals.Success)
                {
                    CaptureCollection cc_vals = m_vals.Groups["pvals"].Captures;
                    for (int j = 0; j < cc_vals.Count; j++)
                    {
                        Console.WriteLine("\t\t'" + cc_vals[j].Value + "'");
                    }
                }

            }
        }
        Console.WriteLine("-------------------------");
    }
}

出力

Key =   BEGIN
Value = VEVENT
-------------------------
Key =   CREATED
Value = 20120504T163940Z
-------------------------
Key =   DTEND
Value = 20120504T130000
Parameters:
        'TZID' =
                'America/Chicago'
-------------------------
Key =   DTSTAMP
Value = 20120504T164000Z
-------------------------
Key =   DTSTART
Value = 20120504T120000
Parameters:
        'TZID' =
                ''
                'America/Chicago'
        'Next' =
                ''
        'last' =
                '"this:;;;:="'
        'final' =
                ''
-------------------------
Key =   LAST-MODIFIED
Value = 20120504T163940Z
-------------------------
Key =   SEQUENCE
Value = 0
-------------------------
Key =   SUMMARY
Value = Test 1
-------------------------
Key =   TRANSP
Value = OPAQUE
-------------------------
Key =   UID
Value = 21F61281-FB76-467F-A2CC-A666688BD9B5
-------------------------
Key =   X-RADICALE-NAME
Value = 21F61281-FB76-467F-A2CC-A666688BD9B5.ics
-------------------------
Key =   END
Value = VEVENT
-------------------------
于 2012-06-14T19:33:28.970 に答える
1

試す:

(?<key>[^:;]*)[:;](?<value>[^\s]*)

C# スニペット:

Regex regex = new Regex(
@"(?<key>[^:;]*)[:;](?<value>[^\s]*)",
RegexOptions.None
);

コロンまたはセミコロン以外の任意の文字列をキーとして取り、空白以外の文字列を値として取ります。

テストしたり、変更を加えたりしたい場合は、私のブログにある正規表現チェッカーをチェックしてください: http://blog.stevekonves.com/2012/01/an-even-better-regex-tester/ (Silverlight が必要)

于 2012-06-14T18:07:21.373 に答える
1

RegEx の代わりに単純な ICAL ファイルの場合は、行に分割して IndexOf(":") を使用するだけで十分な場合があります。

既存の ICAL パーサーと関連する質問 ical+C#があるかどうかを確認してください。

于 2012-06-14T18:03:57.187 に答える
0

個人的には、ファイルの各行に対して string.Split(':') を使用します。これには、正規表現を再学習したくない場合でも、読みやすく理解しやすいという利点があります。

于 2012-06-14T18:04:25.423 に答える
0

これをいくつかの例で実行し、希望どおりに動作するかどうかを確認してください。分割または IndexOf に関する他のコメントを受け取りますが、区切り文字がコロンまたはセミコロンのいずれかであると予想している場合は、おそらく正規表現の方が適切です。

string line = "LAST-MODIFIED:20120504T163940Z";
var p = Regex.Match(line, "(.*)?(:|;)(.*)$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Singleline);
Console.WriteLine(p.Groups[0].Value);
Console.WriteLine(p.Groups[1].Value);
Console.WriteLine(p.Groups[2].Value);
Console.WriteLine(p.Groups[3].Value);
于 2012-06-14T18:08:44.303 に答える