区切り文字の空白で文字列を分割したい。ただし、引用符で囲まれた文字列をインテリジェントに処理する必要があります。たとえば、次のような文字列の場合
"John Smith" Ted Barry
John Smith、Ted、Barry の 3 つの文字列が返されます。
それをいじった後、これに正規表現を使用できます。「すべて一致」に相当するものを実行します。
((?<=("))[\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'
上記の例を使用した正規表現の内訳は、次の場所で確認できます。
とはいえ、正規表現はすべての解決策になるべきではありません-私はただ楽しんでいました。この例には、Unicode文字や記号の処理など、多くのエッジケースがあります。この種のタスクには、実証済みの真のライブラリを使用することをお勧めします。これを使用する前に、他の回答を確認してください。
この醜いコードを試してみてください。
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);
さて、私はあなたが望むことといくつかのことを行う小さなスニペットを作成しました. あなたがそれ以上の条件を指定しなかったので、私はトラブルを経験しませんでした. 私はこれが汚い方法であることを知っており、おそらくすでに作成されたものでより良い結果を得ることができます. しかし、プログラミングの楽しみのために、ここに例を示します。
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 が出力されます。
それが役に立てば幸い
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
これは私自身のバージョンで、 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] を返す必要があります。