9

このような文字列をトークン化したい

String line = "a=b c='123 456' d=777 e='uij yyy'";

このようにベースを分割することはできません

String [] words = line.split(" ");

次のようなトークンを取得するためにどのように分割できますか

a=b
c='123 456'
d=777
e='uij yyy';  
4

11 に答える 11

9

これを行う最も簡単な方法は、単純な有限状態マシンを手動で実装することです。つまり、文字列を一度に 1 文字ずつ処理します。

  • スペースをヒットしたら、トークンを壊します。
  • 引用をヒットすると、別の引用をヒットするまで文字を取得し続けます。
于 2009-10-01T00:26:24.377 に答える
3

元の文字列のフォーマットによっては、Java の「分割」メソッドのパラメーターとして正規表現を使用できるはずです。例については、ここをクリックしてください

ただし、この例では、このタスクに必要な正規表現を使用していません。

この SO スレッドをガイドラインとして使用することもできます(PHP ではありますが) 必要なものに非常に近いことを行います。それを少し操作するとうまくいくかもしれません(ただし、引用符を出力の一部にするかどうかは問題を引き起こす可能性があります)。正規表現はほとんどの言語で非常に似ていることに注意してください。

編集: このタイプのタスクをさらに進めすぎると、正規表現の機能を超える可能性があるため、単純なパーサーを作成する必要がある場合があります。

于 2009-10-01T00:29:20.750 に答える
3
line.split(" (?=[a-z+]=)")

正しく与える:

a=b
c='123 456'
d=777
e='uij yyy'

キー構造が変更された場合に備えて、必ず [a-z+] 部分を適応させてください。

編集:ペアの値部分に「=」文字がある場合、このソリューションは悲惨に失敗する可能性があります。

于 2010-06-21T07:15:26.717 に答える
1

StreamTokenizerが役立ちますが、'=' でブレークするように設定するのが最も簡単ですが、引用符で囲まれた文字列の先頭で常にブレークするためです。

String s = "Ta=b c='123 456' d=777 e='uij yyy'";
StreamTokenizer st = new StreamTokenizer(new StringReader(s));
st.ordinaryChars('0', '9');
st.wordChars('0', '9');
while (st.nextToken() != StreamTokenizer.TT_EOF) {
    switch (st.ttype) {
    case StreamTokenizer.TT_NUMBER:
        System.out.println(st.nval);
        break;
    case StreamTokenizer.TT_WORD:
        System.out.println(st.sval);
        break;
    case '=':
        System.out.println("=");
        break;
    default:
        System.out.println(st.sval);
    }
}

出力

Ta
=
b
c
=
123 456
d
=
777
e
=
uij yyy

数字を英字に変換する 2 行を省略すると、 が得d=777.0られます。これは役に立つかもしれません。

于 2009-10-01T01:14:48.913 に答える
1

仮定:

  • 変数名 (割り当て 'a=b' の 'a') は 1 以上の長さにすることができます
  • 変数名 (割り当て 'a=b' の 'a') に空白文字を含めることはできません。それ以外は問題ありません。
  • 入力の検証は必要ありません (入力は有効な a=b 形式であると想定されます)

これは私にとってはうまくいきます。

入力:

a=b abc='123 456' &=777 #='uij yyy' ABC='slk slk'              123sdkljhSDFjflsakd@*#&=456sldSLKD)#(

出力:

a=b
abc='123 456'
&=777
#='uij yyy'
ABC='slk slk'             
123sdkljhSDFjflsakd@*#&=456sldSLKD)#(

コード:

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexTest {

    // SPACE CHARACTER                                          followed by
    // sequence of non-space characters of 1 or more            followed by
    // first occuring EQUALS CHARACTER       
    final static String regex = " [^ ]+?=";


    // static pattern defined outside so that you don't have to compile it 
    // for each method call
    static final Pattern p = Pattern.compile(regex);

    public static List<String> tokenize(String input, Pattern p){
        input = input.trim(); // this is important for "last token case"
                                // see end of method
        Matcher m = p.matcher(input);
        ArrayList<String> tokens = new ArrayList<String>();
        int beginIndex=0;
        while(m.find()){
            int endIndex = m.start();
            tokens.add(input.substring(beginIndex, endIndex));
            beginIndex = endIndex+1;
        }

        // LAST TOKEN CASE
        //add last token
        tokens.add(input.substring(beginIndex));

        return tokens;
    }

    private static void println(List<String> tokens) {
        for(String token:tokens){
            System.out.println(token);
        }
    }


    public static void main(String args[]){
        String test = "a=b " +
                "abc='123 456' " +
                "&=777 " +
                "#='uij yyy' " +
                "ABC='slk slk'              " +
                "123sdkljhSDFjflsakd@*#&=456sldSLKD)#(";
        List<String> tokens = RegexTest.tokenize(test, p);
        println(tokens);
    }
}
于 2009-10-01T01:27:00.613 に答える
1

または、トークン化のための正規表現と、キー/値をマップに追加するだけの小さなステート マシンを使用します。

String line = "a = b c='123 456' d=777 e =  'uij yyy'";
Map<String,String> keyval = new HashMap<String,String>();
String state = "key";
Matcher m = Pattern.compile("(=|'[^']*?'|[^\\s=]+)").matcher(line);
String key = null;
while (m.find()) {
    String found = m.group();
    if (state.equals("key")) {
        if (found.equals("=") || found.startsWith("'"))
            { System.err.println ("ERROR"); }
        else { key = found; state = "equals"; }
    } else if (state.equals("equals")) {
        if (! found.equals("=")) { System.err.println ("ERROR"); }
        else { state = "value"; }
    } else if (state.equals("value")) {
        if (key == null) { System.err.println ("ERROR"); }
        else {
            if (found.startsWith("'"))
                found = found.substring(1,found.length()-1);
            keyval.put (key, found);
            key = null;
            state = "key";
        }
    }
}
if (! state.equals("key"))  { System.err.println ("ERROR"); }
System.out.println ("map: " + keyval);

プリントアウト

map: {d=777, e=uij yyy, c=123 456, a=b}

いくつかの基本的なエラー チェックを行い、値から引用符を取り除きます。

于 2013-01-24T22:17:02.120 に答える
0
public static void main(String[] args) {
String token;
String value="";
HashMap<String, String> attributes = new HashMap<String, String>();
String line = "a=b c='123  456' d=777 e='uij yyy'";
StringTokenizer tokenizer = new StringTokenizer(line," ");
while(tokenizer.hasMoreTokens()){
        token = tokenizer.nextToken();
    value = token.contains("'") ? value + " " + token : token ;
    if(!value.contains("'") || value.endsWith("'")) {
           //Split the strings and get variables into hashmap 
           attributes.put(value.split("=")[0].trim(),value.split("=")[1]);
           value ="";
    }
}
    System.out.println(attributes);
}

出力: {d=777, a=b, e='uij yyy', c='123 456'}

この場合、連続するスペースは、値内の単一のスペースに切り捨てられます。ここで属性付きハッシュマップには値が含まれています

于 2010-06-21T08:06:17.970 に答える
0

このソリューションは、一般的かつコンパクトです (事実上、cletus の回答の正規表現バージョンです)。

String line = "a=b c='123 456' d=777 e='uij yyy'";
Matcher m = Pattern.compile("('[^']*?'|\\S)+").matcher(line);
while (m.find()) {
  System.out.println(m.group()); // or whatever you want to do
}

つまり、引用符で囲まれた文字列またはスペース以外の文字の組み合わせである一連の文字をすべて見つけます。ネストされた引用符はサポートされていません (エスケープ文字はありません)。

于 2009-10-01T04:13:25.417 に答える
-1
java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(line, " ");
while (tokenizer.hasMoreTokens()) {
    String token = tokenizer.nextToken();
    int index = token.indexOf('=');
    String key = token.substring(0, index);
    String value = token.substring(index + 1);
}
于 2009-10-01T01:15:36.830 に答える
-2

「=」で分割して、結果の配列の各ペアからトークンを作成しようとしましたか?

于 2009-10-01T00:36:49.107 に答える