7

区切り文字の空白で文字列を分割したい。ただし、引用符で囲まれた文字列をインテリジェントに処理する必要があります。たとえば、次のような文字列の場合

"John Smith" Ted Barry 

John Smith、Ted、Barry の 3 つの文字列が返されます。

4

5 に答える 5

10

それをいじった後、これに正規表現を使用できます。「すべて一致」に相当するものを実行します。

((?<=("))[\w ]*(?=("(\s|$))))|((?<!")\w+(?!"))

Javaの例:

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

public class Test
{ 
    public static void main(String[] args)
    {
        String someString = "\"Multiple quote test\" not in quotes \"inside quote\" \"A work in progress\"";
        Pattern p = Pattern.compile("((?<=(\"))[\\w ]*(?=(\"(\\s|$))))|((?<!\")\\w+(?!\"))");
        Matcher m = p.matcher(someString);

        while(m.find()) {
            System.out.println("'" + m.group() + "'");
        }
    }
}

出力:

'Multiple quote test'
'not'
'in'
'quotes'
'inside quote'
'A work in progress'

上記の例を使用した正規表現の内訳は、次の場所で確認できます。

http://regex101.com/r/wM6yT9


とはいえ、正規表現はすべての解決策になるべきではありません-私はただ楽しんでいました。この例には、Unicode文字や記号の処理など、多くのエッジケースがあります。この種のタスクには、実証済みの真のライブラリを使用することをお勧めします。これを使用する前に、他の回答を確認してください。

于 2012-05-22T03:12:23.890 に答える
4

この醜いコードを試してみてください。

    String str = "hello my dear \"John Smith\" where is Ted Barry";
    List<String> list = Arrays.asList(str.split("\\s"));
    List<String> resultList = new ArrayList<String>();
    StringBuilder builder = new StringBuilder();
    for(String s : list){
        if(s.startsWith("\"")) {
            builder.append(s.substring(1)).append(" ");
        } else {
            resultList.add((s.endsWith("\"") 
                    ? builder.append(s.substring(0, s.length() - 1)) 
                    : builder.append(s)).toString());
            builder.delete(0, builder.length());
        }
    }
    System.out.println(resultList);     
于 2012-05-22T03:35:13.743 に答える
3

さて、私はあなたが望むことといくつかのことを行う小さなスニペットを作成しました. あなたがそれ以上の条件を指定しなかったので、私はトラブルを経験しませんでした. 私はこれが汚い方法であることを知っており、おそらくすでに作成されたものでより良い結果を得ることができます. しかし、プログラミングの楽しみのために、ここに例を示します。

    String example = "hello\"John Smith\" Ted Barry lol\"Basi German\"hello";
    int wordQuoteStartIndex=0;
    int wordQuoteEndIndex=0;

    int wordSpaceStartIndex = 0;
    int wordSpaceEndIndex = 0;

    boolean foundQuote = false;
    for(int index=0;index<example.length();index++) {
        if(example.charAt(index)=='\"') {
            if(foundQuote==true) {
                wordQuoteEndIndex=index+1;
                //Print the quoted word
                System.out.println(example.substring(wordQuoteStartIndex, wordQuoteEndIndex));//here you can remove quotes by changing to (wordQuoteStartIndex+1, wordQuoteEndIndex-1)
                foundQuote=false;
                if(index+1<example.length()) {
                    wordSpaceStartIndex = index+1;
                }
            }else {
                wordSpaceEndIndex=index;
                if(wordSpaceStartIndex!=wordSpaceEndIndex) {
                    //print the word in spaces
                    System.out.println(example.substring(wordSpaceStartIndex, wordSpaceEndIndex));
                }
                wordQuoteStartIndex=index;
                foundQuote = true;
            }
        }

        if(foundQuote==false) {
            if(example.charAt(index)==' ') {
                wordSpaceEndIndex = index;
                if(wordSpaceStartIndex!=wordSpaceEndIndex) {
                    //print the word in spaces
                    System.out.println(example.substring(wordSpaceStartIndex, wordSpaceEndIndex));
                }
                wordSpaceStartIndex = index+1;
            }

            if(index==example.length()-1) {
                if(example.charAt(index)!='\"') {
                    //print the word in spaces
                    System.out.println(example.substring(wordSpaceStartIndex, example.length()));
                }
            }
        }
    }

これは、"John Smith" の前や "Basi German" の後の "hello" という単語など、引用符の前後にスペースで区切られていない単語もチェックします。

文字列を変更すると"John Smith" Ted Barry、出力は 3 つの文字列になります。1) "John Smith" 2) Ted 3) Barry

この例の文字列は、hello"John Smith" Ted Barry lol"Basi German"hello で、1)hello 2)"John Smith" 3)Ted 4)Barry 5)lol 6)"Basi German" 7)hello が出力されます。

それが役に立てば幸い

于 2012-05-22T03:35:29.793 に答える
1

commons-lang には、これを行うための StrTokenizer クラスがあり、java-csv ライブラリもあります。

StrTokenizer の例:

String params = "\"John Smith\" Ted Barry"
// Initialize tokenizer with input string, delimiter character, quote character
StrTokenizer tokenizer = new StrTokenizer(params, ' ', '"');
for (String token : tokenizer.getTokenArray()) {
   System.out.println(token);
}

出力:

John Smith
Ted
Barry
于 2012-05-22T03:35:18.047 に答える
1

これは私自身のバージョンで、 http://pastebin.com/aZngu65y (コメントに投稿)からクリーンアップしたものです。Unicode を処理できます。余分なスペースをすべてクリーンアップします (引用符内であっても) - これは、必要に応じて良い場合も悪い場合もあります。エスケープされた引用符はサポートされていません。

private static String[] parse(String param) {
  String[] output;

  param = param.replaceAll("\"", " \" ").trim();
  String[] fragments = param.split("\\s+");

  int curr = 0;
  boolean matched = fragments[curr].matches("[^\"]*");
  if (matched) curr++;

  for (int i = 1; i < fragments.length; i++) {
    if (!matched)
      fragments[curr] = fragments[curr] + " " + fragments[i];

    if (!fragments[curr].matches("(\"[^\"]*\"|[^\"]*)"))
      matched = false;
    else {
      matched = true;

      if (fragments[curr].matches("\"[^\"]*\""))
        fragments[curr] = fragments[curr].substring(1, fragments[curr].length() - 1).trim();

      if (fragments[curr].length() != 0)
        curr++;

      if (i + 1 < fragments.length)
        fragments[curr] = fragments[i + 1];
    }
  }

  if (matched) { 
    return Arrays.copyOf(fragments, curr);
  }

  return null; // Parameter failure (double-quotes do not match up properly).
}

比較のためのサンプル入力:

"sdfskjf" sdfjkhsd "hfrif ehref" "fksdfj sdkfj fkdsjf" sdf sfssd


asjdhj    sdf ffhj "fdsf   fsdjh"
日本語 中文 "Tiếng Việt" "English"
    dsfsd    
   sdf     " s dfs    fsd f   "  sd f   fs df  fdssf  "日本語 中文"
""   ""     ""
"   sdfsfds "   "f fsdf

(2 行目は空、3 行目はスペース、最後の行は形式が正しくありません)。予想される出力はさまざまですが、ベースラインとしては、最初のケースは [sdfskjf, sdfjkhsd, hfrif ehref, fksdfj sdkfj fkdsjf, sdf, sfssd] を返す必要があります。

于 2012-05-22T04:23:00.360 に答える