2

コマンドラインスイッチのキーと値のペアを解析するために正規表現を使用しようとしています。ここに私がこれまでに持っているものがあります:

(?<=(^-{1,2}| -{1,2}|^/| /))(?<name>[\w]+)[ :"]*(?<value>[\w.?=&+ :/|\\]*)(?=[ "]|$)

すべてを適切に解析しているようです...ほとんど。値にハイフンが含まれている場合、一致するとクラップアウトします。以下のすべてのテスト例で機能するようにこれを微調整するにはどうすればよいですか?

テスト例 (すべて有効):

-s  -i:C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\ -h:local:host -d:theDB
-o:"C:\temp\db\" -s -r -host:localhost --d theDB
-s  -i:"C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB -Scripts\" -h:localhost -d:theDB
-s  -d http://www.theproject.com -h:localhost -d:theDB
-i:"C:\Users\Fozzie\Workspace\TheProject\TheProject_Stack_1_5\db\DB Scripts\" --h:localhost -d:theDB
-h:localhost -i:"C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack_1_5\db\DB Scripts\"  -d:theDB
--d theDB   -o:"C:\temp\db\" -host=local-host     -r

値の部分が次のような場合、正規表現は失敗します

"C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\"

または"local-host"その中のハイフンが原因です。新しいスイッチの始まりと見なされます。

PS: getops のような既定のオプション ライブラリは使いたくありません。私は正規表現を正しくすることに興味があります。

ありがとう。

更新: 詳細が不明で申し訳ありません: これは .NET 正規表現です。

4

2 に答える 2

3

.NET ソリューション — 投機的

この推奨される .NET ソリューションは「推奨」にすぎません。私は .NET を使用しておらず、どのマシンでもテストする方法がありません (.NET の正規表現テスト Web サイトはありますか?)。.NET には Perl のオプションに類似した可読性のためのオプションがないという前提で、動作中の Perl ソリューションを使用して、心配のない部分とコメントを削除し、すべてを 1 行にまとめ<mark>ました。 . Perl regex の 5 つの部分に対応する 5 組の括弧がまだ見つかります。私はそれが非捕獲グループであると仮定しています。<pad>x(?:...)

(?:-{1,2}|/)(?<name>\w+)(?:[=:]?|\s+)(?<value>[^-\s"][^"]*?|"[^"]*")?(?=\s+[-/]|$)

また、.NET は、Perl のg修飾子に似たメカニズムを提供し、前のパスで中断した場所で 2 番目 (またはそれ以降) のパスで文字列をスキャンできるようにするメカニズムを提供していると思います。または、試合が終了した場所を何らかの方法で特定し、そこからスキャンを再開することもできます。

Perl ソリューション — 検証済み

これは、私が Perl 正規表現を使用して思いついたのと同じくらい優れています (Mac OS X 10.7.5 上の Perl 5.16.0 でテスト済み)。

#!/usr/bin/env perl
use strict;
use warnings;

# Original regex split into 5 sections:
# C1          (?<=(^-{1,2}|\ -{1,2}|^/|\ /))
# C2          (?<name>[\w]+)
# C3          [ :"]*
# C4          (?<value>[\w.?=&+ :/|\\]*)
# C5          (?=[ "]|$)

my $rx = qr%(?<mark>  -{1,2}|/ )                        (?# Was C1)
            (?<name>  \w+ )                             (?# Was C2)
            (?<pad>   (?: [=:]?|\s+ ))                  (?# Was C3)
            (?<value> (?: [^-\s"][^"]*? | "[^"]*" ))?   (?# Was C4)
            (?=\s+[-/]|$)                               (?# Was C5)
           %x;

while (my $line = <DATA>)
{
    chomp $line;
    print "\nLine: $line\n";
    while ($line =~ m/$rx/g)
    {
        my($mark, $name, $pad, $value) = ($1, $2, $3, $4 // "");
        print "Found: mark $mark name <<$name>> pad <<$pad>> value <<$value>>\n";
    }
}

__DATA__
-s  -i:C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\ -h:local:host -d:theDB
-o:"C:\temp\db\" -s -r -host:localhost --d theDB
-s  -i:"C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB -Scripts\" -h:localhost -d:theDB
-s  -d http://www.theproject.com -h:localhost -d:theDB
-i:"C:\Users\Fozzie\Workspace\TheProject\TheProject_Stack_1_5\db\DB Scripts\" --h:localhost -d:theDB
-h:localhost -i:"C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack_1_5\db\DB Scripts\"  -d:theDB
--d theDB   -o:"C:\temp\db\" -host=local-host     -r
-s -i:C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\ -h:local:host -d:theDB
/d theDB   /o:"C:\temp\db\" /host=local-host     /r
/d theDB /o:"C:\temp\db\" /host=local-host /r /t
-s:C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\ -h:local:host -d:theDB

スクリプトの大部分はあまり興味深いものではありません。外側の while ループは、ファイルのデータ セクション (marker の後のマテリアル__DATA__) を 1 行ずつ読み取り、検証のために出力し、その行で正規表現を繰り返し実行してコンポーネント (マーカー、名前、パディング、および値)、それらを出力します。データの大部分は、質問で提供されたものです (ありがとう!)。データの最後の 3 行は、最初に提供されたものと比べて余分です。

すべての興奮は正規表現にあります。/x読みやすくするために、正規表現に空白を許可するためにPerl の修飾子を使用しました。これは、前にバックスラッシュを付けるか、角括弧で囲まない限り、空白は重要ではないことを意味します (この標本には重要な空白はありません)。オリジナルと同じように表記を使用(?<name> ...)してピースを識別しましたが、名前は使用されていないため省略できます。(?# Was Cn)パーツは純正コメントです。

  1. マークは 1 つまたは 2 つのダッシュまたはスラッシュです。--?それを書く別の短い方法になります。
  2. 名前は英数字の文字列です。これは、「最初の文字が数字ではない可能性がある」ことを強制しようとするものではありません。
  3. パッドは、名前と値を区切ります。単一の等号またはコロン、または空白の文字列を指定できます。内部(?: ...)は非キャプチャ グループ化演算子です。
  4. 値はオプションです (-sサンプル データの最初の行の最初の位置にあるオプションには値がありません)。構成は次のとおりです。ダッシュ、二重引用符、または空白以外で始まる文字列の後に、引用符以外の貪欲でない文字列が続きます。または二重引用符、非引用符の文字列、および別の二重引用符。
  5. 後続のゼロ幅コンテキスト (C5) は、1 つ以上の空白文字の後にダッシュまたはスラッシュが続くか、または EOS のいずれかです。値のパターンは貪欲ではないため、貪欲な後続コンテキストは、オプション値の後の末尾の空白を食い尽くします。

出力は次のとおりです。

Line: -s  -i:C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\ -h:local:host -d:theDB
Found: mark - name <<s>> pad << >> value <<>>
Found: mark - name <<i>> pad <<:>> value <<C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\>>
Found: mark - name <<h>> pad <<:>> value <<local:host>>
Found: mark - name <<d>> pad <<:>> value <<theDB>>

Line: -o:"C:\temp\db\" -s -r -host:localhost --d theDB
Found: mark - name <<o>> pad <<:>> value <<"C:\temp\db\">>
Found: mark - name <<s>> pad <<>> value <<>>
Found: mark - name <<r>> pad <<>> value <<>>
Found: mark - name <<host>> pad <<:>> value <<localhost>>
Found: mark -- name <<d>> pad << >> value <<theDB>>

Line: -s  -i:"C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB -Scripts\" -h:localhost -d:theDB
Found: mark - name <<s>> pad << >> value <<>>
Found: mark - name <<i>> pad <<:>> value <<"C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB -Scripts\">>
Found: mark - name <<h>> pad <<:>> value <<localhost>>
Found: mark - name <<d>> pad <<:>> value <<theDB>>

Line: -s  -d http://www.theproject.com -h:localhost -d:theDB
Found: mark - name <<s>> pad << >> value <<>>
Found: mark - name <<d>> pad << >> value <<http://www.theproject.com>>
Found: mark - name <<h>> pad <<:>> value <<localhost>>
Found: mark - name <<d>> pad <<:>> value <<theDB>>

Line: -i:"C:\Users\Fozzie\Workspace\TheProject\TheProject_Stack_1_5\db\DB Scripts\" --h:localhost -d:theDB
Found: mark - name <<i>> pad <<:>> value <<"C:\Users\Fozzie\Workspace\TheProject\TheProject_Stack_1_5\db\DB Scripts\">>
Found: mark -- name <<h>> pad <<:>> value <<localhost>>
Found: mark - name <<d>> pad <<:>> value <<theDB>>

Line: -h:localhost -i:"C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack_1_5\db\DB Scripts\"  -d:theDB
Found: mark - name <<h>> pad <<:>> value <<localhost>>
Found: mark - name <<d>> pad <<:>> value <<theDB>>

Line: --d theDB   -o:"C:\temp\db\" -host=local-host     -r
Found: mark -- name <<d>> pad << >> value <<theDB>>
Found: mark - name <<o>> pad <<:>> value <<"C:\temp\db\">>
Found: mark - name <<host>> pad <<=>> value <<local-host>>
Found: mark - name <<r>> pad <<>> value <<>>

Line: -s -i:C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\ -h:local:host -d:theDB
Found: mark - name <<s>> pad <<>> value <<>>
Found: mark - name <<i>> pad <<:>> value <<C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\>>
Found: mark - name <<h>> pad <<:>> value <<local:host>>
Found: mark - name <<d>> pad <<:>> value <<theDB>>

Line: /d theDB   /o:"C:\temp\db\" /host=local-host     /r
Found: mark / name <<d>> pad << >> value <<theDB  >>
Found: mark / name <<o>> pad <<:>> value <<"C:\temp\db\">>
Found: mark / name <<host>> pad <<=>> value <<local-host    >>
Found: mark / name <<r>> pad <<>> value <<>>

Line: /d theDB /o:"C:\temp\db\" /host=local-host /r /t
Found: mark / name <<d>> pad << >> value <<theDB>>
Found: mark / name <<o>> pad <<:>> value <<"C:\temp\db\">>
Found: mark / name <<host>> pad <<=>> value <<local-host>>
Found: mark / name <<r>> pad <<>> value <<>>
Found: mark / name <<t>> pad <<>> value <<>>

Line: -s:C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\ -h:local:host -d:theDB
Found: mark - name <<s>> pad <<:>> value <<C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\>>
Found: mark - name <<h>> pad <<:>> value <<local:host>>
Found: mark - name <<d>> pad <<:>> value <<theDB>>
于 2012-10-30T14:37:18.073 に答える
0

編集:ソリューションを変更して、D:\ huheue \ hello \myname.pdfのようなFILEPATHSと一致できるようにしました

これは私が持っている正規表現であり、かなりうまく機能します。

(--?[a-zA-Z]+)[:\s=]?([A-Z]:(?:\\[\w\s-]+)+\\?(?=\s-)|\"[^\"]*\"|[^-][^\s]*)?

デモ

それがあなたが必要としていたものであり、次のような出力が得られることを願っています。

MATCH 1
1.  [0-2]   `-s`
MATCH 2
1.  [3-5]   `-i`
2.  [6-70]  `C:\Users\Fozzie\Workspace\TheProject\TheProaject-Stack-1_5\db\DB Scripts`
MATCH 3
1.  [80-82] `-h`
2.  [83-93] `local:host`
ETC
于 2012-10-30T12:19:28.863 に答える