Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

Java5の正規表現の挙動がJava1.4と違う気がする...

こんにちは。

これまで Java1.4 をずっと使っていましたが
最近、Java5 を使うようになりました。

以前は以下のようなコードを書いた場合、
「--A」で始まる行を
正規表現で削除する事ができていたのですが、
Java5 の String#replaceAll(String, String) だと
パターンに一致しなくなったのかわかりませんが、
行が削除されないようです。

    String sql = null;
    {
        ByteArrayOutputStream sqlBuff = new ByteArrayOutputStream();
        PrintWriter pw = new PrintWriter(sqlBuff);

        pw.println("    SELECT ");
        pw.println("       EMPNO  ");
        pw.println("      ,ENAME ");
        pw.println("    FROM ");
        pw.println("      EMP ");
        pw.println("    WHERE ");
        pw.println("          EMPNO = ? ");
        pw.println("--A   AND ENAME = ? ");
        pw.println("    ORDER BY ");
        pw.println("      EMPNO ");
        pw.close();
        sql = sqlBuff.toString();
    }

    String afterSql = sql;
    afterSql = afterSql.replaceAll("\\-\\-.*\\n", "");
    afterSql = afterSql.replaceAll("\\n[\\ ]*\\n", "\n");
    System.out.println(afterSql);

ネットで調べてみても Java5 から正規表現の仕様や挙動が
変わったというような情報は見当たらないのですが、
何か情報をご存知の方がいらっしゃったら
教えていただけるとうれしいです。

よろしくお願いします。

10

回答

84070

閲覧

10件の回答

評価

0

1.5でも1.6でも、「--A」で始まる行は削除されますよ。それにしても、-やスペースの前に\\を書く必要はないと思いますが…。

評価

0

こんにちは ranco さん。
回答ありがとうございます。

> 1.5でも1.6でも、「--A」で始まる行は
> 削除されますよ。
>
私の環境では「JDK 1.5.0_12」だけを
インストールしているのですが、
前述したコードを動かしても
「--A」で始まる行が削除されないです。

public class TryCode extends TestCase
{
    public void testCode()
    {
        // 前述したコード
    }
}

というクラスを作ってみて
Eclipse 3.3.1.1 のJUnit 3.8 で
TryCode#testCode() を実行して確認しているのですが
削除されないようです。

他の方の環境だと問題なく動作するのであれば
私のPCの環境の問題かもですね(−−;)

> それにしても、-やスペースの前に
> \\を書く必要はないと思いますが…。

おっしゃるとおりですね。(^^;)
試しに簡単なコードを書いてるときに
どの記号がメタキャラクタだったか覚えてなかったので
付けちゃってました。

以後、気をつけます。

評価

0

一度、EclipseもJUnitもヌキで、ハダカのjavac/javaコマンドでやってみたら?

評価

0

下記のようなバッチファイルとJavaファイルを作成後、
バッチファイルを実行してみましたが
結果は変わりませんでした。

JDK1.5.0_12 を使っていますが、
最新版は JDK1.5.0_15 があるようなので
そちらで試した方がいいかもしれませんね。


【Test.bat】
-----------------------------------------------------------------------
@echo off

"%JAVA_HOME%\bin\javac" -encoding utf8 "%~dp0.\TryCode.java"
"%JAVA_HOME%\bin\java" "TryCode"

pause
-----------------------------------------------------------------------


【TryCode.java】
-----------------------------------------------------------------------
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;

public class TryCode
{
    public static void main(String[] args)
    {
        System.out.println("start");
        try
        {
            new TryCode().testCode();
        }
        catch (Exception e )
        {
            e.printStackTrace(System.err);
        }
        finally
        {
            System.out.println("end");
        }
    }

    public void testCode() throws Exception
    {
        String sql = null;
        {
            ByteArrayOutputStream sqlBuff = new ByteArrayOutputStream();
            PrintWriter pw = new PrintWriter(sqlBuff);

            pw.println("    SELECT ");
            pw.println("       EMPNO  ");
            pw.println("      ,ENAME ");
            pw.println("    FROM ");
            pw.println("      EMP ");
            pw.println("    WHERE ");
            pw.println("          EMPNO = ? ");
            pw.println("--A   AND ENAME = ? ");
            pw.println("    ORDER BY ");
            pw.println("      EMPNO ");
            pw.close();
            sql = sqlBuff.toString();
        }

        String afterSql = sql;
        afterSql = afterSql.replaceAll("\\-\\-.*\\n", "");
        afterSql = afterSql.replaceAll("\\n[\\ ]*\\n", "\n");
        System.out.println(afterSql);
    }
}
-----------------------------------------------------------------------


【コンソールの出力結果】
-----------------------------------------------------------------------
start
    SELECT
       EMPNO
      ,ENAME
    FROM
      EMP
    WHERE
          EMPNO = ?
--A   AND ENAME = ?
    ORDER BY
      EMPNO

end
続行するには何かキーを押してください . . .
-----------------------------------------------------------------------

評価

0

http://java.sun.com/javase/ja/6/docs/ja/api/java/util/regex/Pattern.html#MULTILINE

複数行モードを有効にします。 
複数行モードでは、表現 ^ と $ は、それぞれ行末記号または入力シーケンスの末尾の直後または直前にマッチします。デフォルトでは、これらの表現は入力シーケンス全体の先頭と末尾にだけマッチします。 
複数行モードは、埋め込みフラグ表現 (?m) を使用して有効にすることもできます。

String afterSql = sql;
//afterSql = afterSql.replaceAll("\\-\\-.*\\n", "");
afterSql = afterSql.replaceAll("(?m)^--.*$", "");

評価

0

情報ありがとうございました。

「複数行モード」については
JavaDoc で確認し、意識していました。

-- で始まる行を空文字に変換するだけなら
「複数行モード」を有効にしなくても

afterSql = afterSql.replaceAll("\\-\\-.*\\n", "");
    ↓↓↓
afterSql = afterSql.replaceAll("--.*", "");

のように修正すればちゃんと動くなぁ
というのは確認できていたのですが、
どちらかというとネックになっているのは

afterSql = afterSql.replaceAll("\\n[\\ ]*\\n", "\n");

の空行を削除する部分です。
※今回は行頭以外で -- が使われる事は
 無いという前提で正規表現を書いています。

説明不足でお手数をおかけしてすみません。

Java1.4 までは正常に動作していたのに
Java5 に変えたら想定した動作をしなくなったので、
Java の正規表現の挙動が変わったのかな〜と
思った次第です。

評価

0

1.5.0_13でも1.5.0_09でも結果は同じです。
正規表現中で^も$も使われていないので、MULTILINEモードは関係ありません。

-encoding utf8というヘンなものが要らない、クリーンなコマンドラインで試してみてください。

評価

0

> -encoding utf8というヘンなものが要らない、クリーンなコマンドラインで試してみてください。

すいません。
普段からJavaのソースコードは BOM 無しの UTF-8 で書いているので
-encoding オプションを付けていました。

今回試したソースにはマルチバイト文字が含まれていないから
おっしゃるとおり、オプションは要りませんでしたね。

それで、-encoding オプションをはずして試してみましたが、
やっぱり結果は一緒でした。

仕事の都合上、Javaの他のバージョンをPCにインストールできないので、
仮想マシンに JDK1.5.0_15 をインストールして試してみます。

結果は後ほど、投稿したいと思います。

評価

0

環境書いてないから推測だけど、多分こんなオチだと思う。
afterSql = afterSql.replaceAll("--.*", "");
afterSql = afterSql.replaceAll("\\r\\n\\r\\n", "\\r\\n");

というか、一行毎に処理すれば、正規表現使う必要もなく簡単なのに。

評価

0

JDK1.5.0_15 で試してみたけどだめでした。
...と投稿しようかと思ったら
5678 さんの回答を見て \r を忘れてた事に気づきました。

結果、以下のように修正したらちゃんと
想定している動作になりました。

    afterSql = afterSql.replaceAll("--.*", "");
    afterSql = afterSql.replaceAll("\\n[ \\r]*\\n", "\r\n");

いろいろ助言をいただいたみなさん
ありがとうございました。

やっぱり Java の正規表現の挙動が変わるなんて事は
そうそう無いですよね〜。(^^;)

> というか、一行毎に処理すれば、正規表現使う必要もなく簡単なのに。

正規表現止めて一行毎の処理に変えようかな〜とは思いましたが
プログラム書く手間とパフォーマンスがどうなるか
自信が無かったのでやってませんでした。

正規表現の処理もだいぶ重い処理だと思いますが、
ちゃんと書けば一行毎に処理した方が
ぜんぜん速いんでしょうか?

一行毎に処理する場合は BufferedReader 辺りを使って
処理する事になるのかな?と考えています。

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。