2012-01-15 8 views
7

私は以下のようにサービスからの応答を受け取ります。これを解析してMapにするにはどうすればよいですか?私は最初に空白で区切りを考えましたが、値に空白が含まれている可能性があるため動作しません。下の応答ののSAキーの値を見てください。このテキストを構文解析する簡単な方法はありますか?

私が考えていた1つのオプションは、空白で分割することです前の文字は二重引用符です。しかし、このための正規表現を書く方法はわかりません。

TX = "0000000000108000001830001" FI = "" OS = "8" CI = "QU01SF1S2032" AW = "SSS" SA = "1525ウィンドワードコンコース" 引用符で

答えて

4

解析。各値が引用符で囲まれていると仮定して、正規表現を使用して各キー/値のペアを見つけることさえできます。私の唯一の質問は、値に埋め込み引用符が含まれている場合のルールは何ですか?これもグループにあなたの#1と#を与える

(\w+)="([^"]*)" 

:たとえば

(...「\」、彼らが使用してエスケープされたりなどはかかわらず、これは現在、下記に計上されていません?) 2を使用して、それぞれキーと値を提供することができます。

すべてのペアが見つかるまで、JavaのMatcher.find()メソッドを使用してループで実行します。

サンプルコード:

String input = "TX=\"0000000000108000001830001\" FI=\"\" OS=\"8\" CI=\"QU01SF1S2032\" AW=\"SSS\" SA=\"1525 Windward Concourse\""; 

Pattern p = Pattern.compile("\\s*(\\w+)=\"([^\"]*)\"\\s*"); 

Matcher m = p.matcher(input); 
while(m.find()){ 
    System.out.println(m.group(1)); 
    System.out.println(m.group(2)); 
} 

出力:私はquoteChar()機能を使用していないが、

TX 
0000000000108000001830001 
FI 

OS 
8 
CI 
QU01SF1S2032 
AW 
SSS 
SA 
1525 Windward Concourse 
+2

さて、一重引用符を使用してください。それはGroovyとタグ付けされています:) –

+0

@DaveNewton - 我々はOPのための練習としてそれを残します。 :-) – ziesemer

+0

@ziesemer - +1。しかし、二重引用符で印刷された「=」の後には、「0000000000108000001830001」と表示されます。 –

2

StreamTokenizer、高速です。例は、here,hereおよびhereである。

コンソール:

 
TX=0000000000108000001830001 
FI= 
OS=8 
CI=QU01SF1S2032 
AW=SSS 
SA=1525 Windward Concourse 
Count: 6 
0.623 ms 

コード:XMLかもしれないと思われるテキストのルックスによって

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.StreamTokenizer; 
import java.io.StringReader; 

/** @see https://stackoverflow.com/questions/8867325 */ 
public class TokenizerTest { 

    private static final String s = "" 
     + "TX=\"0000000000108000001830001\" FI=\"\" OS=\"8\" " 
     + "CI=\"QU01SF1S2032\" AW=\"SSS\" SA=\"1525 Windward Concourse\""; 
    private static final char equal = '='; 
    private static final char quote = '"'; 
    private static StreamTokenizer tokens = new StreamTokenizer(
     new BufferedReader(new StringReader(s))); 

    public static void main(String[] args) { 
     long start = System.nanoTime(); 
     tokenize(); 
     long stop = System.nanoTime(); 
     System.out.println((stop - start)/1000000d + " ms"); 
    } 

    private static void tokenize() { 
     tokens.ordinaryChar(equal); 
     tokens.quoteChar(quote); 
     try { 
      int count = 0; 
      int token = tokens.nextToken(); 
      while (token != StreamTokenizer.TT_EOF) { 
       if (token == StreamTokenizer.TT_WORD) { 
        System.out.print(tokens.sval); 
        count++; 
       } 
       if (token == equal) { 
        System.out.print(equal); 
       } 
       if (token == quote) { 
        System.out.println(tokens.sval); 
       } 
       token = tokens.nextToken(); 
      } 
      System.out.println("Count: " + count); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

StreamTokenizerについて教えてください –

+0

'quoteChar()'を試してみてください。 ;上記より。 – trashgod

+0

私はこの解決策が過度に複雑だと思います。パフォーマンスの制約が大きい場合を除いて、正規表現を使用するなどの簡単な解決方法をお勧めします(パフォーマンスが_is_ a制約の場合は、これが本当に正規表現より高速かどうかを調べる必要があります)。 – epidemian

3

。それはそうですか、またはそのテキストはサービスの生の応答ですか?それはあなたがGroovyのXmlSlurperで簡単に解析できるXMLの場合:

def input = '<root TX="0000000000108000001830001" FI="" OS="8" CI="QU01SF1S2032" AW="SSS" SA="1525 Windward Concourse"></root>' 
def xml = new XmlSlurper().parseText(input) 

def map = xml.attributes() 

それはXMLではない場合map変数は[CI:QU01SF1S2032, AW:SSS, TX:0000000000108000001830001, OS:8, FI:, SA:1525 Windward Concourse]

だろう、あなたはziesemer's answerに従うと、正規表現を使用することができます。 Mapを生成し、彼の答えのgroovierバージョンは次のようになります。

def input = 'TX="0000000000108000001830001" FI="" OS="8" CI="QU01SF1S2032" AW="SSS" SA="1525 Windward Concourse"' 
def match = input =~ /(\w+)="([^"]*)"/ 

def map = [:] 
match.each { 
    map[it[1]] = it[2] 
} 

mapの結果は前と同じになります。

+0

次のようにすることもできます: 'def map =(list as match).collectEntries {[(it [1]):it [2]]}' –

+0

@tim_yates Nice!私は 'match'オブジェクトで' collectEntries'を呼び出そうとしましたが、そのメソッドはなく、標準的な反復メソッドしか持っていません。私は最初にリストに変換するとは思わなかった。ところで、 'inject'もトリック= Dを行うことができます – epidemian

関連する問題