3

任意の " 文字で Java Strings を分割する必要があります。主なことは、その前の文字がバックスラッシュ ( \ ) ではない可能性があることです。

したがって、これらの文字列は次のように分割されます。

asdnaoe"asduwd"adfdgb         =>   asdnaoe, asduwd, adfgfb
addfgmmnp"fd asd\"das"fsfk    =>   addfgmmnp, fd asd\"das, fsfk

正規表現を使用してこれを達成する簡単な方法はありますか? (コーダーである私にとって最も簡単なため、RegExを使用します。また、パフォーマンスは問題ではありません...)

前もって感謝します。

私はこのようにそれを解決しました:

    private static String[] split(String s) {
    char[] cs = s.toCharArray();

    int n = 1;

    for (int i = 0; i < cs.length; i++) {
        if (cs[i] == '"') {
            int sn = 0;

            for (int j = i - 1; j >= 0; j--) {
                if (cs[j] == '\\')
                    sn += 1;
                else
                    break;
            }

            if (sn % 2 == 0)
                n += 1;
        }
    }

    String[] result = new String[n];

    int lastBreakPos = 0;
    int index = 0;
    for (int i = 0; i < cs.length; i++) {
        if (cs[i] == '"') {
            int sn = 0;

            for (int j = i - 1; j >= 0; j--) {
                if (cs[j] == '\\')
                    sn += 1;
                else
                    break;
            }

            if (sn % 2 == 0) {
                char[] splitcs = new char[i - lastBreakPos];

                System.arraycopy(cs, lastBreakPos, splitcs, 0, i - lastBreakPos);
                lastBreakPos = i + 1;

                result[index] = new StringBuilder().append(splitcs).toString();
                index += 1;
            }
        }
    }

    char[] splitcs = new char[cs.length - (lastBreakPos + 1)];

    System.arraycopy(cs, lastBreakPos, splitcs, 0, cs.length - (lastBreakPos + 1));

    result[index] = new StringBuilder().append(splitcs).toString();

    return result;
}

とにかく、素晴らしい回答をありがとうございました! (ああ、それにもかかわらず、@biziclop または @Alan Moore のバージョンのいずれかを使用します。それらは短く、おそらくより効率的です! =)

4

3 に答える 3

4

もちろん、そのまま使用してください

(?<!\\)"

クイック PowerShell テスト:

PS> 'addfgmmnp"fd asd\"das"fsfk' -split '(?<!\\)"'
addfgmmnp
fd asd\"das
fsfk

ただし、これは分割されません\\"(エスケープされたバックスラッシュの後に通常の引用符が続きます [少なくともほとんどの C ライクな言語のエスケープ規則では])。ただし、任意の長さの後読みはサポートされていないため、Java ではこれを実際に解決することはできません。

PS> 'addfgmmnp"fd asd\\"das"fsfk' -split '(?<!\\)"'
addfgmmnp
fd asd\\"das
fsfk

"通常、実際にはエスケープされていないため、残りの部分に分割する適切なソリューションが期待されます。

于 2012-05-29T19:01:53.470 に答える
2

この問題は Java 正規表現で解決できます。使用しないでくださいsplit()

public static void main(String[] args) throws Exception
{
  String[] strs = {
      "asdnaoe\"asduwd\"adfdgb",
      "addfgmmnp\"fd asd\\\"das\"fsfk"
  };

  for (String str : strs)
  {
    System.out.printf("%n%-28s=>  %s%n", str, splitIt(str));
  }
} 


public static List<String> splitIt(String s)
{
  ArrayList<String> result = new ArrayList<String>();
  Matcher m = Pattern.compile("([^\"\\\\]|\\\\.)+").matcher(s);
  while (m.find())
  {
    result.add(m.group());
  }
  return result;
}

出力:

asdnaoe"asduwd"adfdgb       => [asdnaoe, asduwd, adfdgb]

addfgmmnp"fd asd\"das"fsfk  => [addfgmmnp, fd asd\"das, fsfk]

コア正規表現 は[^"\\]|\\.、バックスラッシュや引用符、またはバックスラッシュの後に何かが続くものではないものをすべて消費し\\\"ます。\\\"

于 2012-05-30T05:17:14.977 に答える
1

参考までに、エスケープも処理する正規表現以外のソリューションを次に示し\ます。(実際には、これは単純化できます。START_NEW状態は実際には必要ありませんが、読みやすい方法で記述しようとしました。)

public class Splitter {

    private enum State {
        IN_TEXT, ESCAPING, START_NEW;
    }

    public static List<String> split( String source ) {
        LinkedList<String> ret = new LinkedList<String>();
        StringBuilder sb = new StringBuilder();
        State state = State.START_NEW;
        for( int i = 0; i < source.length(); i++ ) {
            char next = source.charAt( i );
            if( next == '\\' && state != State.ESCAPING ) {
                state = State.ESCAPING;
            } else if( next == '\\' && state == State.ESCAPING ) {
                state = State.IN_TEXT;
            } else if( next == '"' && state != State.ESCAPING ) {
                ret.add( sb.toString() );
                sb = new StringBuilder();
                state = State.START_NEW;
            } else {
                state = State.IN_TEXT;
            }
            if( state != State.START_NEW ) {
                  sb.append( next );
            }
        }
        ret.add( sb.toString() );
        return ret;
    }

}
于 2012-05-29T20:23:09.313 に答える