2011-08-01 28 views
3

文字列をトークン化しようとしています。限り何のクォート文字がすべて存在しないとしてもです:引用符付き文字列をトークン化

string:tokens ("abc def ghi", " "). 
["abc","def","ghi"] 

しかし、文字列:トークン/ 2は、引用符で囲まれた文字列でずっと私を助けません。私は必要なのトークン化される文字列をとる関数、区切りと引用符文字である

string:tokens ("abc \"def xyz\" ghi", " "). 
["abc","\"def","xyz\"","ghi"] 

:それは期待通りに動作します。ような何か:今

tokens ("abc \"def xyz\" ghi", " ", "\""). 
["abc","def xyz","ghi"] 

私は車輪の再発明を開始する前に、私の質問は:

があり、そのような機能や標準のlibsで同様のものですか?

EDIT:

OK、私は私の独自の実装を書いたが、私はまだ元の質問への答えに非常に興味があります。これまでのところ私のコードは次のとおりです:

tokens (String) -> tokens (String, [], []). 

tokens ([], Tokens, Buffer) -> 
    lists:map (fun (Token) -> string:strip (Token, both, $") end, Tokens ++ [Buffer]); 

tokens ([Character | String], Tokens, Buffer) -> 
    case {Character, Buffer} of 
     {$ , [] } -> tokens (String, Tokens, Buffer); 
     {$ , [$" | _] } -> tokens (String, Tokens, Buffer ++ [Character]); 
     {$ , _} -> tokens (String, Tokens ++ [Buffer], []); 
     {$", [] } -> tokens (String, Tokens, "\""); 
     {$", [$" | _] } -> tokens (String, Tokens ++ [Buffer ++ "\""], []); 
     {$", _} -> tokens (String, Tokens ++ [Buffer], "\""); 
     _ -> tokens (String, Tokens, Buffer ++ [Character]) 
    end. 
+0

正規表現を考えましたか?簡単にする方法の1つかもしれません。 –

答えて

4

です:あなただけではなく、スペースの空白に基づいて分割したい場合は

> re:split("abc \"def xyz\" ghi", " \"|\" ", [{return, list}]). 
["abc","def xyz","ghi"] 

また"\s\"|\"\s"を使用することができます。

これを入力ファイルから解析する場合は、strip_split/2estringから使用するとよいでしょう。

1

reモジュールを使用できます。これにはsplit/3機能が付属しています。例えばの場合:正規表現は、あなたが使用できる一般的なケースでは許容されている場合

 
re:split("abc \"def xyz \"ghi", "[(\s\")\s\"]", [{return, list}]). 
["abc",[],"def","xyz",[],"ghi"] 

二番目の引数は正規表現(あなたは空のリストを削除するために私の例を微調整する必要があるかもしれません...)

+0

ありがとうございますが、あなたの出力(空の要素を無視する)は '[" abc "、" def "、" xyz "、" ghi "]'です。私が必要とするのはあなたの例 '[" abc "、" def xyz "、" ghi "]'です。私はあなたのアプローチでこれを得ることができますか? – Hyperboreus

+0

それは実際にはもっと簡単になります:) 're:split(" abc \ "def xyz \" ghi "、" \ s \ ""、[{return、list}])。 –

+0

しかし、 '' abc "、" def "、" def xyz "、" ghi "]'に '' tokens( "abc def \" def xyz \ "ghi"、 ""、\ "")このソリューションでは、代わりに '[" abc def "、" def xyz "、" ghi "]'を取得します。 –

1

これは私がそれを書くだろうか約ある(テストしていない!):

tokens(String) -> lists:reverse(tokens(String, outside_quotes, [])). 

tokens([], outside_quotes, Tokens) -> 
    Tokens; 
tokens(String, outside_quotes, Tokens) -> 
    {Token, Rest0} = lists:splitwith(fun(C) -> (C != $) and (С != $"), String), 
    case Rest0 of 
    [] -> [Token | Tokens]; 
    [$ | Rest] -> tokens(Rest, outside_quotes, [Token | Tokens]); 
    [$" | Rest] -> tokens(Rest, inside_quotes, [Token | Tokens]) 
    end; 
tokens(String, inside_quotes, Tokens) -> 
    %% exception on an unclosed quote 
    {Token, [$" | Rest]} = lists:splitwith(fun(C) -> С != $", String), 
    tokens(Rest, outside_quotes, [Token | Tokens]). 
2

string:tokens ("abc \"def ghi\" foo.bla", " .\"").はスペース、ポイントと二重引用符で文字列をトークン化します。結果:["abc", "def", "ghi", "foo", "bla"]。クォートされた部分を保存したい場合は、トークン/レクサーの作成を検討することをお勧めします。正規表現はこの作業にはあまり適していないからです。

関連する問題