2011-12-28 7 views
1

私は元の質問hereを尋ねて、Rubyと正規表現が混在した実用的な応答を得ました。今、私の純粋主義者は知りたいです:これは正規表現で行うことができますか?私の腸はそれができると言います。 bash 2.0にはABNFがありますが、文字列エスケープは含まれていません。チャレンジ:シェル割り当てのような設定ラインのためのRegex-onlyトークナイザ

スペック

典型的なコンフィギュレーションファイルからのbash風味スクリプトまたは(2)キーと値の設定から、(1)変数(「キー」)の割り当てである入力ラインが与えられますpostgresql.confのように、この正規表現(または正規表現の対)は、それらのキャプチャを使用してそのキーに新しい値を代入できるような方法でキーと値を取得する必要があります。

シェルフレーバー付きおよび設定済みの行には、別の正規表現を使用できます。呼び出し元はどちらを使用するかを知っています。

ここに50ポイントの賞金があります。賞金を2日間追加することはできませんので、それまでの回答は受け付けませんが、すぐに回答を開始することができます。私にDFA

  • 正規表現について何かを教える代わりに、2
  • の単一正規表現を使用して

    • 可読性(名前付きキャプチャグループ、定義を経由して(DEFINE)または{0}?)
    • :あなたがのためにポイントを獲得します性能は、該当する場合
    • はupvotedはじめ
    • 技術を使用する最初の

    例:

    入力

    export RAILS_ENV=production 
    

    を考えると、私はRubyで書くことができる必要があります:

    match = THE_REGEX.match("export RAILS_ENV=production") 
    newline = "export #{match[:key]}=#{match[:value]}" 
    

    テストケース:シェルスタイル

    RAILS_ENV=development  # Don't forget to change this for TechCrunch 
    HOSTNAME=`cat /etc/hostname` 
    plist=`cat "/Applications/Sublim\`e Text 2.app/Content's/Info.plist"` 
    
    # Optional bonus input: "#" present in the string 
    FORMAT=" ##0.00 passe\`" #comment 
    

    テストケース:設定スタイル、この課題の目的のために

    listen_addresses = 127.0.0.1 #localhost only by default 
    # listen_addresses = 0.0.0.0 commented out, should not match 
    

    、「正規表現」と「正規表現」は同じことを意味し、私はルビーを好むものの両方が、あなたが好きな普通の風味を参照することができます1.9-互換性があります。

  • +1

    あなた 'plistのは='行方不明\ 'を持っているようです。 – kennytm

    +0

    修正しました。ありがとうございます! –

    答えて

    2

    私はフルスペックとまさにあなたがグループをキャプチャ値にしたいについてはよく分からないが、これはテストケースのために働く必要があります。

    / 
    ^\s*+ 
    
    (?:export\s++)? 
    (?<key>\w++) 
    
    \s*+ 
    = 
    \s*+ 
    
    (?<value> 
        (?> "(?:[^"\\]+|\\.)*+" 
        | '(?:[^'\\]+|\\.)*+' 
        | `(?:[^`\\]+|\\.)*+` 
        | [^#\n\r]++ 
    ) 
    ) 
    
    \s*+ 
    (?:#.*+)? 
    $ 
    /mx; 
    

    は、エスケープとのコメントや引用符を処理します。

    Perl/PCREフレーバと引用符。Perlで


    使用例:

    my $re = qr/ 
        ^\s*+ 
    
        (?:export\s++)? 
        (?<key>\w++) 
    
        \s*+ 
        = 
        \s*+ 
    
        (?<value> 
         (?> "(?:[^"\\]+|\\.)*+" 
         | '(?:[^'\\]+|\\.)*+' 
         | `(?:[^`\\]+|\\.)*+` 
         | [^#\n\r]++ 
        ) 
        ) 
    
        \s*+ 
        (?:\#.*+)? 
        $ 
    /mx; 
    
    my $str = <<'_TESTS_'; 
    RAILS_ENV=development  # Don't forget to change this for TechCrunch 
    HOSTNAME=`cat /etc/hostname` 
    plist=`cat "/Applications/Sublim\`e Text 2.app/Content's/Info.plist"` 
    
    # Optional bonus input: "#" present in the string 
    FORMAT=" ##0.00 passe\`" #comment 
    
    listen_addresses = 127.0.0.1 #localhost only by default 
    # listen_addresses = 0.0.0.0 commented out, should not match 
    
    TEST="foo'bar\"baz#" 
    TEST='foo\'bar"baz#\\' 
    _TESTS_ 
    
    
    for(split /[\r\n]+/, $str){ 
        print "line: $_\n"; 
        print /$re/? "match: $1, $2\n": "no match\n"; 
        print "\n"; 
    } 
    

    出力:

    line: RAILS_ENV=development  # Don't forget to change this for TechCrunch 
    match: RAILS_ENV, development 
    
    line: HOSTNAME=`cat /etc/hostname` 
    match: HOSTNAME, `cat /etc/hostname` 
    
    line: plist=`cat "/Applications/Sublim\`e Text 2.app/Content's/Info.plist"` 
    match: plist, `cat "/Applications/Sublim\`e Text 2.app/Content's/Info.plist"` 
    
    line: # Optional bonus input: "#" present in the string 
    no match 
    
    line: FORMAT=" ##0.00 passe\`" #comment 
    match: FORMAT, " ##0.00 passe\`" 
    
    line: listen_addresses = 127.0.0.1 #localhost only by default 
    match: listen_addresses, 127.0.0.1 
    
    line: # listen_addresses = 0.0.0.0 commented out, should not match 
    no match 
    
    line: TEST="foo'bar\"baz#" 
    match: TEST, "foo'bar\"baz#" 
    
    line: TEST='foo\'bar"baz#\\' 
    match: TEST, 'foo\'bar"baz#\\' 
    
    +1

    最初に試してください。ありがとう! –

    関連する問題