2017-01-25 12 views
0

数字で始まり(NBSPと1-2のスペースで始まる)一連の "レコード"を持つテキストファイルを解析しようとしていますが、数百文字の文字と数字を含み、改行をスパンしますが、予期せぬもので終わる。レコードの終わりを識別するための唯一の方法は、以下の正規表現で一致させることができる開始マーカー、の次のインスタンスを打つことです。正規表現で分割し、Javaで一致する区切り文字をキャプチャしますか?

\\d{1,4}\\u00A0\\s+ 

コンテンツ手は予測不可能な改行と、入力されたので、私それらを取り除いた。それは私に文字列を残します。

1 blah blah blah 2 blah blah blah ... 875 blah blah blah 

私は記録が終了したことを知っている唯一の方法は、次のレコードのIDを打つことであるので、私は上記の正規表現で分割してみました。これは、ファイルをレコードに正しく分割しますが、レコードIDを省略してキャプチャする必要があります。私はJavaのドキュメントをチェックしましたが、分割される動的な値のキャプチャには何もありません。レコード番号をキャプチャグループにしようとしましたが、そのデータは結果の配列に保持されません。

この質問(Java String Regex split and capture splitted portion)は類似しているようですが、質問者は各テキスト断片の終わりを知っています。一方、私はそれぞれがどこから始まるのか分かっています。

別の方法で分割することはできますが、分割正規表現によるテキストの一致は維持されますか?

おかげ

答えて

2

あなただけが、あなたの試合で他のテキストは、(チェックのようなfoobarした後場合は試合でbarを含めずに)、あなたが探していることを含めずに、あなたのテキストの後にいくつかの他のテキストが存在するかどうかを確認したい場合look-around mechanismまたはより正確には、正面が先読み(?=...)です。

だから、split("(?=\\d{1,4}\\u00A0\\s+)")で始めることができます。これは、それの後ろにNBSPといくつかの空白を持つ一連の1-4桁の前に分割されます。この通報は、テキスト

1234[nbsp]___ 

のように、これは( |でマークされた)場所

|1234[nbsp]___ 
1|234[nbsp]___ 
12|34[nbsp]___ 
123|4[nbsp]___ 

を記述しかし、我々は数字の間の分割を許可したくないということです。そのような分割を防ぐために条件を追加する必要があります。だから、「スプリットの場所の前に数字を入れることはできない」と言うことができればいいですね。これを行うには、(?<!\\d)のように見える(?<!...)の背後に否定的な表情を使用することができます。

split("(?<!\\d)(?=\\d{1,4}\\u00A0\\s+)") 
+0

ああ。非常に素晴らしい。 後継の場合:この分割方法により、分割線ごとに正規表現にマッチした動的区切り文字を保持することができました。 – user2029783

2

split()を使用していますが、例えば、あなた自身の正規表現のループを記述しないでください

String input = "...your input..."; 
Matcher m = Pattern.compile("\\d{1,4}\\u00A0\\s+").matcher(input); 
int prev = 0; 
while (m.find()) { 
    String prevText = input.substring(prev, m.start()); 
    prev = m.end(); 
    String delimiter = m.group(); 
    // ... code here ... 
} 
String tailText = input.substring(prev); // text after last delimiter 
// ... code here ... 
+0

バリアント:

最終的な溶液は、ように見えることができる。? 'Pattern.compile("(*)(\\ dを{1,4} \\ u00A0 \\ S +) "、Pattern.DOTALL); while(m.find()){String prevText = m.group(1);文字列区切り文字= m.group(2); ...} '。あるいは、終わりの終わりのないビットを気にするなら、 'String delimiter; Pattern.compile( "(。*?)(\\ d {1,4} \\ u00A0 \\ s + | $)"、Pattern.DOTALL); while(! "" .equals(delimiter)){m.find();}文字列prevText = m.group(1);区切り文字= m.group(2); ...} '。 –

+0

@DavidKnipe区切り文字はターミネータではなく接頭辞であるため、最初の部分は無用です。 --- 2番目の部分では、 '' group() '](https://docs.oracle.com/javase/8/docs/api/java/util)の呼び出し時に発生するため、IllegalStateExceptionが発生したばかりです。 /regex/Matcher.html#group-int-) 'find()'の後にfalseが返されます。 javadocの中にそうそう言います。 ---まあ、それは何らかの形で、デリミタの初期化されていないコンパイルエラーを修正した後に起こることです。 – Andreas

+0

'find()'は正規表現に '| $'を追加したので、falseを返すべきではありませんので、最後にデリミタなしで一致するはずです。 'String delimiter;'を 'String delimiter = null;'に変更します。 –

関連する問題