代码之家  ›  专栏  ›  技术社区  ›  kal

在Java中用空间标记字符串

  •  9
  • kal  · 技术社区  · 15 年前

    我想标记这样的字符串

    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';  
    
    11 回复  |  直到 8 年前
        1
  •  9
  •   cletus    15 年前

    最简单的方法是手工实现一个简单的有限状态机。换句话说,一次处理字符串一个字符:

    • 当你击中一个空格时,断开一个标记;
    • 当你点击一个引语时,不断地获取字符,直到你点击另一个引语。
        2
  •  3
  •   Community CDub    8 年前

    根据原始字符串的格式,您应该能够使用正则表达式作为Java“拆分”方法的参数: Click here for an example .

    不过,该示例不使用执行此任务所需的正则表达式。

    您也可以使用 this SO thread 作为一个指导方针(尽管它是在PHP中),它的作用非常接近于您所需要的。稍微操作一下可能会有一些技巧(尽管引号是否是输出的一部分,可能会导致一些问题)。请记住,regex在大多数语言中非常相似。

    编辑 :对这类任务的深入研究可能会超过regex的功能,因此您可能需要创建一个简单的解析器。

        3
  •  3
  •   cherouvim    15 年前
    line.split(" (?=[a-z+]=)")
    

    正确给出:

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

    确保您对[A-Z+]部分进行了调整,以防您的键结构发生变化。

    编辑 :如果对的值部分有“=”字符,此解决方案可能会失败。

        4
  •  1
  •   Stephen Denne    15 年前

    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
    

    如果省略将数字字符转换为字母的两行,则 d=777.0 可能对你有用。

        5
  •  1
  •   hashable    15 年前

    假设:

    • 变量名(“a”在赋值中为“a=b”)的长度可以是1或更多
    • 变量名(“a”在赋值中为“a=b”)不能包含空格字符,其他都可以。
    • 不需要验证输入(假定输入为有效的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);
        }
    }
    
        6
  •  1
  •   asusu    12 年前

    或者,使用一个用于标记化的regex,以及一个只将key/val添加到映射的小型状态机:

    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}
    

    它执行一些基本的错误检查,并去掉值的引号。

        7
  •  0
  •   Brett Kail    15 年前

    这个解决方案既普通又紧凑(实际上是克莱特斯答案的regex版本):

    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
    }
    

    换句话说,查找所有由带引号的字符串或非空格字符组合而成的字符;不支持嵌套引号(没有转义字符)。

        8
  •  0
  •   kmkswamy    15 年前
    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'

    在这种情况下,连续空间将被截断为值中的单个空间。 这里属性化的hashmap包含值

        9
  •  0
  •   YoungHobbit Zhixiu Lu    8 年前
     import java.io.*;
     import java.util.Scanner;
    
     public class ScanXan {
      public static void main(String[] args) throws IOException {
    
        Scanner s = null;
    
        try {
            s = new Scanner(new BufferedReader(new FileReader("<file name>")));
    
            while (s.hasNext()) {
                System.out.println(s.next());
               <write for output file>
            }
        } finally {
            if (s != null) {
                s.close();
            }
        }
     }
    }
    
        10
  •  -1
  •   Raymond Kroeker    15 年前
    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);
    }
    
        11
  •  -2
  •   rajax    15 年前

    您是否尝试用“=”拆分并从结果数组的每对中创建一个标记?