2017-08-24 14 views
3

私は私のMOVEを返す開始し奇妙な行動

 String myStr = " MOVE ELSE MOVE EXT-LNGSHRT-AMT-C TO WK-UNSIGNED-LNGSHRT-AMT COMPUTE WK-SHORT-AMT = EXT-LNGSHRT-AMT-C * -1."; 

JavaのようなものにmyStr変更する場合

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

public class Test { 
    public static void main(String[] args) { 
     String myStr = " ELSE MOVE EXT-LNGSHRT-AMT-C TO WK-UNSIGNED-LNGSHRT-AMT COMPUTE WK-SHORT-AMT = EXT-LNGSHRT-AMT-C * -1."; 
     String verbsRegex = "\\s+(ACCEPT|ADD|ALTER|CALL|CANCEL|CLOSE|COMPUTE|DELETE|DISPLAY|DIVIDE|ELSE|EXIT|EVALUATE|EXEC|GO|GOBACK|IF|INITIALIZE|INSPECT|INVOKE|MERGE|MOVE|MULTIPLY|OPEN|PERFORM|READ|RELEASE|RETURN|REWRITE|SEARCH|SET|SORT|START|STOP|STRING|SUBTRACT|UNSTRING|WRITE|COPY|CONTINUE|WHEN)\\s+"; 

     Pattern p = Pattern.compile(verbsRegex); 
     Matcher m = p.matcher(myStr); 
     System.out.println("------------------------------------"); 
     while (m.find()) { 
      System.out.println(myStr.substring(m.start(),m.end())); 
      System.out.println("("+ m.group(1) + ")"); 
     } 
     System.out.println("------------------------------------"); 
    } 
} 

変数myStr内の文字列「MOVE」存在を見つけることができませんコードを次に示します。しかし、この場合、ELSEは逃してしまいます!

この動作についての説明は何ですか?私はここで何かを見逃していますか?

ありがとうございます。

+0

"MOVE"や "ELSE"のようなテキストでしか動作しませんが、ELSEの前にはELSEがないために、 "空白文字の後に続く空白文字が続き、空白が多くなります"空白。 – gtgaxiola

+0

あなたはいつも同じグ​​ループを印刷しています... – pedromss

答えて

1

あなたはm.group(0)m.group()を(group()リターンがgroup(0)の結果以来、両方が同じである)を使用することができます。また、全体一致が(グループ(1)と同じように)[]のような文字で囲みます。

ので、代わりの

System.out.println("["+m.group()+"]"); 

System.out.println(myStr.substring(m.start(),m.end())); 

使用して、あなたは何が一致していること[ ELSE ][ COMPUTE ]であることがわかります。表示されているように、検索されたトークンの後に可能なすべてのスペースも合わせています。しかし、あなたの正規表現は少なくとも1つの空白で始まるの一致を必要とするので、一致しない空白がないため、[MOVE ]はマッチングできません。この問題を解決するにはlookaround mechanismzero-length(一致部分を消費しない)を使用できます。

ので、代わりの\\s+(...)\\s+あなたは

(?<=\\s)(...)(?=\\s) 

としてそれを書き換えることができます。しかし、それに伴う問題は、あなたのトークンもスペースに囲まする必要があることですので、あなたがに配置されているマッチを見つけることができなくなります文字列の開始または終了。

\bのいずれかがword boundaryである可能性があります。それはあなたがIF-ELSEを持っている場合、それは別にIFELSE見つけるだろう/文字列の末尾を開始されるか、または[a-zA-Z0-9_]と非[a-zA-Z0-9_]文字のいずれかの間に配置されているが、それはまた、アルファベット文字と-間の場所を表すことになり場所を表し(...)部分トークンに記載されているものと一致しない単一のトークンとして扱いたい場合でも、

他の解決策は、^$(詳細はhttp://www.regular-expressions.info/anchors.html)で表される文字列の開始と終了を受け入れ、スペースを受け入れることになります。その場合、あなたのソリューションは、ところで、通常、我々はAは、正規表現の残りの部分がどのように見えるかに応じて、全体の正規表現にマッチする十分(になる場合ので、我々は(A|AB)を書くような状況を回避しようと

(?<=\\s|^)(...)(?=\\s|$) 

ようになります。 )ABはテストされません。だから、文字列AABのような正規表現を(A|AB)とすると、AAであり、AABではない2つの一致が見つかるでしょう。そのため、私たちは通常、最も具体的なものから具体性の低いものまで、具体的には(AB|A)のように書こうとしています(または、リテラルの場合は長さに基づいてそれらを注文することができます)。

2

代わり\s+を使用してのあなたは\bWord Boundariesは、グループ内の任意の単語を一致させるために使用することができますので、あなたの正規表現は次のようになります。で

\\b(ACCEPT|...|WHEN)\\b 

出力

------------------------------------ 
ELSE 
(ELSE) 
MOVE 
(MOVE) 
COMPUTE 
(COMPUTE) 
------------------------------------ 
3

\s+をパターンの先頭に\s+の終わりで衝突します。彼らは欲張りです。つまり、それは単語MOVEと一致し、その左側に空白が残らず、一致しないことを意味します。

\s+から\s+?MOVEの両方が一致します。しかし、キャプチャされたすべてのグループに1つ以上の空白文字が必要であることを意味することに注意してください。単語境界やルックアラーでこれを解決できます。全試合の代わりmyStr.substring(m.start(), m.end())を印刷するに