1

こんにちは、テキストを明確に定義されたトークンに転送するクラスを作成しようとしています。

文字列は、次のようなコードに多少似ています(brown) "fox" 'c';。私が取得したいのは(スキャナーからのトークンまたはスリット後の配列のいずれかであり、両方ともうまく機能すると思います)( , brown , ) , "fox" , 'c' , ;(それらは潜在的なトークンであるため)、次のものが含まれます。

  • 'と で引用されたテキスト"
  • 小数点ありまたはなしの数値
  • 括弧、中括弧、セミコロン、等号、シャープ、||、<=、&&

\s+|(?=[;\{\}\(\)]|\b)現在、私はスキャナーでそれを行っています。区切り文字で () などを個別に指定できないという問題がありまし"'。私は本当にそれを避けたいので、いくつかの否定的な先読みを追加しようとしまし"たが、運が悪い.

StreamTokenizer を使用しようとしましたが、異なる引用符が保持されません..

PSサイトを検索してグーグルで検索しようとしましたが、スキャナー関連/正規表現関連の質問がたくさんありますが、問題を解決するものを見つけることができませんでした.

編集1: これまでのところ、私は\s+|^|(?=[;{}()])|(?<![.\-/'"])(?=\b)(?![.\-/'"]) 十分に明確ではないかもしれませんが、次のようなものがある場合:

"foo";'bar')(;{

gray fox=-56565.4546;

foo boo="hello"{

私は取得したい:

"foo", ;, 'bar', ), (, ;_{

grayfox=-56565.4546;

fooboo="hello"{

しかし、代わりに私は持っています:

"foo"、、、、、、;'bar'_ )_ (_ ;_{

grayfox=-56565.4546;

fooboo="hello"{

=と残りの間にスペースがある場合、たとえば : は次のようになることに注意してくださいgray fox = -56565.4546;

grayfox=-56565.4546;

上記の正規表現で私がやっていることは次のとおりです。

Scanner scanner = new Scanner(line);
    scanner.useDelimiter(MY_MENTIONED_REGEX_HERE);
    while (scanner.hasNext()) {
       System.out.println("Got: `" + scanner.next() +"`");
       //Some work here

}
4

4 に答える 4

1

アイデアは、特定のケースから一般的に開始することです。次の表現を試してください。

Java string:
"([\"'])(?:[^\"']+|(?!\\1)[\"'])*\\1|\\|\\||<=|&&|[()\\[\\]{};=#]|[\\w.-]+"

Raw pattern:
(["'])(?:[^"']+|(?!\1)["'])*\1|\|\||<=|&&|[()\[\]{};=#]|[\w.-]+

ここでの目標は、架空の区切り文字で分割することではなく、エンティティごとに一致させることです。=代替の順序が優先度を定義することに注意してください (前に置くことはできません=>) 。

新しい仕様の例 ​​(パターンとマッチャーをインポートする必要があります):

String s = "(brown) \"fox\" 'c';foo bar || 55.555;\"foo\";'bar')(;{ gray fox=-56565.4546; foo boo=\"hello\"{";
Pattern p = Pattern.compile("([\"'])(?:[^\"']+|(?!\\1)[\"'])*\\1|\\|\\||<=|&&|[()\\[\\]{};=#]|[\\w.-]+");
Matcher m = p.matcher(s) ;  

 while (m.find()) {
    System.out.println("item = `" + m.group() + "`");
}
于 2013-06-01T10:48:13.313 に答える
0

あなたの問題は主に、1 つの正規表現で多くのことをしようとしているために、その部分の相互作用を理解できないことです。人間として、私たちは皆、この問題を抱えています。

あなたがしていることは、「字句解析」と呼ばれるコンパイラ ビジネスの標準的な処理です。字句解析ジェネレーターは、関心のある個々のトークンごとに正規表現を受け入れ、個々の語彙素を区別できる場合はそれらを選択する状態の複雑なセットを構築します。トークンごとに字句定義を分離することで、トークンを個別に書くのが簡単になり、混乱しなくなります。lexer ジェネレーターを使用すると、すべてのメンバーを「簡単」かつ効率的に認識できます。(特定の引用符を含む語彙素を定義したい場合は、それを行うのは簡単です)。

広く利用可能なパーサージェネレーターのいずれかを参照してください。それらにはすべて、JCup、ANTLR、JavaCC などの字句解析エンジンが含まれています。

于 2013-06-01T16:14:59.960 に答える
0

おそらく、 JFLexなどのスキャナー ジェネレーターを使用すると、正規表現を使用するよりも簡単に目標を達成できるでしょう。

コードを手で書くのが好きだとしても、もう少し構造化したほうがいいと思います。簡単な解決策の 1 つは、認識したいさまざまな種類のトークンをテキストから「消費」しようとする別のメソッドを作成することです。そのような各メソッドは、成功したかどうかを判断できます。このようにして、理解や記述が難しい 1 つの大きなコードではなく、複数の小さなコードのチャンクを使用して、さまざまなトークンを処理できます。

于 2013-06-01T20:10:10.840 に答える