001 /* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016 package org.opengion.fukurou.process; 017 018 import org.opengion.fukurou.util.Argument; 019 import org.opengion.fukurou.util.FileUtil; 020 import org.opengion.fukurou.util.FileString; 021 import org.opengion.fukurou.util.Closer ; 022 import org.opengion.fukurou.util.StringUtil ; 023 import org.opengion.fukurou.util.LogWriter; 024 025 import java.util.Arrays; 026 import java.util.Map ; 027 import java.util.LinkedHashMap ; 028 import java.util.regex.Pattern; 029 import java.util.regex.Matcher; 030 031 import java.io.File; 032 import java.io.PrintWriter; 033 import java.io.BufferedReader; 034 import java.io.IOException; 035 036 /** 037 * Process_Grep は、上流から受け取っ?FileLineModelから、文字?を見つけ?? 038 * ChainProcess インターフェースの実?ラスです? 039 * 040 * 正規表現の keyword を上流から受け取っ?FileLineModel から検索します? 041 * 見つかった対象ファイルから、指定???を置換する?合??change ? 042 * -changeFile で、keyword を置換する文字?を指定して下さ?? 043 * 置換する文字?には、\t と \n の特殊文字が使用できます? 044 * 045 * 処?象は??常は?行づつ読み取りながら処?行います?存在チェ?の場合?? 046 * 見つかった時点で処?中止します?これは、該当?をピ?ア??するのではなく? 047 * 存在して?かど?を判断して、あれ?、下流に流すと?のが目?からです? 048 * keyword を?改行を含?規表現で、検索・置換する?合??useBulkRead 属?? 049 * true に設定してください。これ?、?力ファイルを?して読み込みます? 050 * -ignoreCase は、正規表現の検索時にキーの大?小文字を無視するよ??します? 051 * -notEquals は、結果(見つかればtrue)を反転(見つからなければtrue)します? 052 * これは、行単位ではなく?ファイル単位に判定します?で、change ?した?? 053 * でも?対象行?、見つかった行です?ただし?下流に対して、見つからな? 054 * 場合だけ??継続させます? 055 * -inEncode は、?力ファイルのエンコード指定になります? 056 * -outEncode は、?力ファイルのエンコードや、changeFileで??置換文字?ファイルの 057 * エンコード指定になります?(changeFile は、? 出力ファイルと同じエンコードです?) 058 * これら?エンコードが無??場合?、System.getProperty("file.encoding") で 059 * 求まる?を使用します? 060 * -changeFile を使用することで、?行???に置換することが可能です? 061 * -outfile では、??行ったファイル名?をセーブします? 062 * 063 * 上?プロセスチェインの??タは上流から渡されます?)からのLineModel の 064 * ファイルオブジェクトより?????が含まれて?か検索します? 065 * 上流?ロセスでは、Name 属?として、?File』を持ち、?は、Fileオブジェク? 066 * である、Process_FileSearch を使用するのが?便利です?それ以外?クラス? 067 * 使用する場合でも?Name属?と、File オブジェクトを持つ LineModel を受け渡? 068 * できれば、使用可能です? 069 * 070 * 引数??中に空白を含??合?、ダブルコー??ション("") で括って下さ?? 071 * 引数??の ?』?前後には、空白は挟めません。??key=value の様に 072 * 繋げてください? 073 * 074 * @og.formSample 075 * Process_Grep -keyword=検索?? -ignoreCase=true -outfile=OUTFILE -encode=UTF-8 076 * 077 * -keyword=キーワー? ?検索する語句 078 * [-ignoreCase=大?小文?] ?検索時に大?小文字を区別しな?true)かど?(初期値:区別する[false]) 079 * [-notEquals=判定結果の反転] ?判定結果を反転させ?true)かど?(初期値:反転させない[false]) 080 * [-inEncode=入力エンコー?] ??力ファイルのエンコードタイ? 081 * [-outEncode=出力エンコード] ??力ファイル?換ファイルのエンコードタイ? 082 * [-change=置換文字? ] ??change="ABCD" \t ?\n などの特殊文字が使用できます? 083 * [-changeFile=置換ファイル ] ??changeFile=change.txt こ?ファイルの記述すべてと置換します? 084 * -change と?changeFile は、同時に?できません? 085 * 置換機?使用時?、?、_backup と?ファイルが作?されます? 086 * [-insert=[BEFORE/AFTER] ] : 置換でなく挿入する場合?位置を指定しま?初期値:CHANGE) 087 * スペ?スで区?て数字を記述すると、挿入位置にオフセ?できます? 088 * [-delete=[false/true] ] : 置換でなく削除しま?初期値:false) 089 * [-useBackup=[false/true] ] ?trueは、backupファイルを作?しま?初期値:false) 090 * [-useBulkRead=[false/true]] ?trueは、?力ファイルを?読込しま?初期値:false) 091 * [-display=[false/true] ] ?trueは、検索状況を表示しま?初期値:false) 092 * [-debug=false|true ] ?デバッグ??を標準?力に表示する(true)かしな?false)?初期値:false[表示しない]) 093 * 094 * @version 4.0 095 * @author Kazuhiko Hasegawa 096 * @since JDK5.0, 097 */ 098 public class Process_Grep extends AbstractProcess implements ChainProcess { 099 private static final String[] INSERT_LIST = new String[] { "CHANGE","BEFORE","AFTER" }; 100 101 private Pattern pattern = null; 102 private String keyword = null; 103 private boolean ignoreCase = false; 104 private boolean notEquals = false; 105 private String inEncode = null; 106 private String outEncode = null; 107 private String change = null; 108 private String insert = "CHANGE"; // "CHANGE","BEFORE","AFTER" のどれか 109 private int insOffset = 0; // "BEFORE","AFTER" 時?オフセ? 110 private boolean useBackup = false; 111 private boolean useBulkRead = false; // 4.0.1.0 (2007/12/14) 112 private boolean delete = false; 113 private boolean display = false; 114 private boolean debug = false; // 5.1.2.0 (2010/01/01) 115 116 private int inCount = 0; 117 private int findCount = 0; 118 private int cngCount = 0; 119 120 private static final Map<String,String> mustProparty ; // ?プロパティ???チェ?用 Map 121 private static final Map<String,String> usableProparty ; // ?プロパティ?整合?チェ? Map 122 123 static { 124 mustProparty = new LinkedHashMap<String,String>(); 125 mustProparty.put( "keyword", "検索する語句(??)" ); 126 127 usableProparty = new LinkedHashMap<String,String>(); 128 usableProparty.put( "ignoreCase", "検索時に大?小文字を区別しな?true)かど?? + 129 CR + "(初期値:区別する[false])" ); 130 usableProparty.put( "notEquals", "検索時に判定結果を反転させ?true)かど?? + 131 CR + "(初期値:反転させない[false])" ); 132 usableProparty.put( "inEncode", "入力ファイルのエンコードタイ? ); 133 usableProparty.put( "outEncode", "出力ファイル?換ファイルのエンコードタイ? ); 134 usableProparty.put( "change", "置換文字? ? -change=\"ABCD\" \\t ?\\n などの特殊文字が使用できます?" ); 135 usableProparty.put( "changeFile", "置換文字?ファイル ? -changeFile=change.txt" + 136 CR + "-change と?changeFile は、同時に?できません? + 137 CR + "置換機?使用時?、?、_backup と?ファイルが作?されます?" ); 138 usableProparty.put( "insert", "[BEFORE/AFTER]:置換でなく挿入する場合?位置を指定しま?初期値:CHANGE)" + 139 CR + "スペ?スで区?て数字を記述すると、挿入位置にオフセ?できます?" ); 140 usableProparty.put( "delete", "[false/true]:trueは、置換でなく削除しま?初期値:false)" ); 141 usableProparty.put( "useBackup", "[false/true]:trueは、backupファイルを作?しま?初期値:false)" ); 142 usableProparty.put( "useBulkRead", "[false/true]:trueは、?力ファイルを?読込しま?初期値:false)" ); 143 usableProparty.put( "display", "[false/true]:trueは、検索状況を表示しま?初期値:false)" ); 144 usableProparty.put( "debug", "????を標準?力に表示する(true)かしな?false)? + 145 CR + "(初期値:false:表示しな?" ); 146 } 147 148 /** 149 * ?ォルトコンストラクター? 150 * こ?クラスは、動??されます??ォルトコンストラクターで? 151 * super クラスに対して、?な初期化を行っておきます? 152 * 153 */ 154 public Process_Grep() { 155 super( "org.opengion.fukurou.process.Process_Grep",mustProparty,usableProparty ); 156 } 157 158 /** 159 * プロセスの初期化を行います?初めに??、呼び出されます? 160 * 初期処?ファイルオープン??オープン?に使用します? 161 * 162 * @param paramProcess ??タベ?スの接続???などを持って?オブジェク? 163 */ 164 public void init( final ParamProcess paramProcess ) { 165 Argument arg = getArgument(); 166 167 keyword = arg.getProparty("keyword"); 168 ignoreCase = arg.getProparty("ignoreCase" ,ignoreCase); 169 notEquals = arg.getProparty("notEquals" ,notEquals); 170 inEncode = arg.getProparty("inEncode" ,System.getProperty("file.encoding")); 171 outEncode = arg.getProparty("outEncode" ,System.getProperty("file.encoding")); 172 useBackup = arg.getProparty("useBackup" ,useBackup); 173 useBulkRead = arg.getProparty("useBulkRead" ,useBulkRead); // 4.0.1.0 (2007/12/14) 174 delete = arg.getProparty("delete" ,delete ); 175 insert = arg.getProparty("insert" ,insert ); 176 change = arg.getFileProparty( "change","changeFile",outEncode,false ); 177 display = arg.getProparty("display" ,display); 178 debug = arg.getProparty( "debug" ,debug ); // 5.1.2.0 (2010/01/01) 179 180 if( change != null ) { 181 int adrs = insert.indexOf( ' ' ); // オフセ?数字?有無 182 if( adrs > 0 ) { 183 insOffset = Integer.parseInt( insert.substring( adrs+1 ) ); 184 insert = insert.substring( 0,adrs ); 185 } 186 187 boolean isOK = false; 188 for( int i=0; i<INSERT_LIST.length; i++ ) { 189 if( insert.equalsIgnoreCase( INSERT_LIST[i] ) ) { 190 isOK = true; break; 191 } 192 } 193 if( !isOK ) { 194 String errMsg = "insert は? + Arrays.toString( INSERT_LIST ) 195 + " から?してください? + CR 196 + "-insert=[" + insert + "]" ; 197 throw new RuntimeException( errMsg ); 198 } 199 200 change = StringUtil.replace( change,"\\n",CR ); 201 change = StringUtil.replace( change,"\\t","\t" ); 202 } 203 204 if( delete ) { change = ""; } // 削除は?" ??と置換します? 205 206 if( ignoreCase ) { 207 pattern = Pattern.compile( keyword,Pattern.CASE_INSENSITIVE ); 208 } 209 else { 210 pattern = Pattern.compile( keyword ); 211 } 212 } 213 214 /** 215 * プロセスの終?行います??に??、呼び出されます? 216 * 終???ファイルクローズ??クローズ?に使用します? 217 * 218 * @param isOK ト?タルで、OK?たかど?[true:成功/false:失敗] 219 */ 220 public void end( final boolean isOK ) { 221 // ここでは処?行いません? 222 } 223 224 /** 225 * 引数の LineModel を??るメソ?です? 226 * 変換処?? LineModel を返します? 227 * 後続??行わな?????タのフィルタリングを行う場?は? 228 * null ??タを返します?つまり?null ??タは、後続??行わな? 229 * フラグの代わりにも使用して?す? 230 * なお?変換処?? LineModel と、オリジナルの LineModel が? 231 * 同?、コピ?(クローン)か?、各処?ソ??決めて?す? 232 * ドキュメントに明記されて???合?、副作用が問題になる?合?? 233 * ???とに自?コピ?(クローン)して下さ?? 234 * 235 * @og.rev 4.0.1.0 (2007/12/14) ファイルの?処?応? 236 * @og.rev 5.7.2.2 (2014/01/24) エラー時に??タも?力します? 237 * 238 * @param data オリジナルのLineModel 239 * 240 * @return 処?換後?LineModel 241 */ 242 public LineModel action( final LineModel data ) { 243 inCount++ ; 244 245 final FileLineModel fileData ; 246 if( data instanceof FileLineModel ) { 247 fileData = (FileLineModel)data ; 248 } 249 else { 250 String errMsg = "??タ?FileLineModel オブジェクトではありません? + CR ; 251 throw new RuntimeException( errMsg ); 252 } 253 254 File file = fileData.getFile() ; 255 if( ! file.isFile() ) { 256 if( display ) { println( data.dataLine() ); } // 5.1.2.0 (2010/01/01) display の条件変更 257 return data; 258 } 259 260 final boolean isFind ; 261 try { 262 String fileLine = null; 263 int firstLineNo = -1; 264 if( useBulkRead ) { fileLine = findKeywordAsBulk( file ); } 265 else { firstLineNo = findKeyword( file ); } 266 267 isFind = ( fileLine != null ) || ( firstLineNo >= 0 ) ; 268 269 // 置換??ただし?見つかったとき?み実? 270 if( change != null && isFind ) { 271 // 入力ファイルは、オリジナル_backup ファイルとする。過去のファイルを削除 272 File inFile = new File( file.getPath() + "_backup" ); 273 if( inFile.exists() && !inFile.delete() ) { 274 String errMsg = "??ファイルを削除できませんでした?" + inFile + "]" + CR 275 + "data=[" + data.dataLine() + "]" + CR ; // 5.7.2.2 (2014/01/24) エラー時に??タも?力します? 276 throw new RuntimeException( errMsg ); 277 } 278 279 // オリジナルのファイルを?_backup ファイル名に先に変換する? 280 File fromFile = new File( file.getPath() ); 281 if( !fromFile.renameTo( inFile ) ) { 282 String errMsg = "??ファイルをリネ??きませんでした?" + fromFile + "]" + CR 283 + "data=[" + data.dataLine() + "]" + CR ; // 5.7.2.2 (2014/01/24) エラー時に??タも?力します? 284 throw new RuntimeException( errMsg ); 285 } 286 287 // 変換処?本? 288 if( useBulkRead ) { changeKeywordAsBulk( fileLine,file ); } 289 else { changeKeyword( inFile,file,firstLineNo ); } 290 291 // backup を使わな??合?、削除する? 292 // 4.0.0.0 (2007/11/29) 入れ子if の統? 293 if( ! useBackup && !inFile.delete() ) { 294 String errMsg = "??ファイルを削除できませんでした?" + inFile + "]" + CR 295 + "data=[" + data.dataLine() + "]" + CR ; // 5.7.2.2 (2014/01/24) エラー時に??タも?力します? 296 throw new RuntimeException( errMsg ); 297 } 298 } 299 } 300 catch ( RuntimeException ex ) { 301 String errMsg = "処?にエラーが発生しました?" + data.getRowNo() + "]件目" + CR 302 // + data.toString() ; 303 + "data=[" + data.dataLine() + "]" + CR ; // 5.7.2.2 (2014/01/24) エラー時に??タも?力します? 304 throw new RuntimeException( errMsg,ex ); 305 } 306 307 if( display && ( notEquals ^ isFind ) ) { println( data.dataLine() ); } // 5.1.2.0 (2010/01/01) display の条件変更 308 return ( notEquals ^ isFind ) ? data : null ; 309 } 310 311 /** 312 * キーワードが存在して?かど?をチェ?します? 313 * ここでは?行づつ読み取りながら、最初に見つかった時点で制御を返します? 314 * よって、?行にまたが?keyword でのマッチングは出来ませんが?大きな 315 * ファイル等での検索には、効?です? 316 * 317 * @og.rev 4.0.1.0 (2007/12/14) 新規追? 318 * 319 * @param file 検索??ファイルオブジェク? 320 * 321 * @return ??に見つかった行番号(見つからなければ?1 を返す) 322 */ 323 private int findKeyword( final File file ) { 324 BufferedReader reader = null; 325 326 int firstLineNo = -1; 327 try { 328 reader = FileUtil.getBufferedReader( file,inEncode ); 329 String line ; 330 int lineNo = 0; 331 while((line = reader.readLine()) != null) { 332 lineNo++ ; 333 Matcher mach = pattern.matcher( line ); 334 if( mach.find() ) { 335 if( debug ) { 336 String buf = "DEBUG:\t" + file.getPath() + "(" + lineNo + "): " + line ; 337 println( buf ); 338 } 339 firstLineNo = lineNo; 340 break; 341 } 342 } 343 } 344 catch ( IOException ex ) { 345 String errMsg = "ファイル読取エラーが発生しました?" + file.getPath() + "]" ; 346 throw new RuntimeException( errMsg,ex ); 347 } 348 finally { 349 Closer.ioClose( reader ); 350 } 351 352 return firstLineNo; 353 } 354 355 /** 356 * キーワードが存在して?かど?をチェ?します? 357 * ここでは、ファイルをすべて読み取ってから、チェ?します? 358 * よって、?行にまたが?keyword でのマッチングが可能です? 359 * 360 * @og.rev 4.0.1.0 (2007/12/14) 新規追? 361 * 362 * @param file 検索??ファイルオブジェク? 363 * 364 * @return 検索??ファイルの??化情報(ただし?見つからなければ、null) 365 */ 366 private String findKeywordAsBulk( final File file ) { 367 368 boolean isFind = false; 369 370 FileString sf = new FileString(); 371 sf.setFilename( file.getPath() ); 372 sf.setEncode( inEncode ); 373 String line = sf.getValue(); 374 375 Matcher mach = pattern.matcher( line ); 376 if( mach.find() ) { 377 if( debug ) { println( "DEBUG:\t" + file.getPath() ); } 378 isFind = true; 379 } 380 381 return ( isFind ) ? line : null; 382 } 383 384 /** 385 * キーワードを????に置き換えます? 386 * useBackup 属?に true を指定した?合?置き換え後?、backup ファイルは? 387 * オリジナル_backup と?名称に変わります? 388 * ここでは?行づつ読み取りながら、変換処?行います? 389 * よって、?行にまたが?keyword でのマッチングは出来ませんが?大きな 390 * ファイル等での置換でも?メモリの使用量?抑えられます? 391 * 392 * @og.rev 4.0.1.0 (2007/12/14) 置換??独立させます? 393 * 394 * @param inFile 検索??入力ファイルオブジェク? 395 * @param outFile 変換後?出力ファイルオブジェク? 396 * @param firstLineNo キーワードが存在した場合???の行番号 397 */ 398 private void changeKeyword( final File inFile,final File outFile,final int firstLineNo ) { 399 400 BufferedReader reader = FileUtil.getBufferedReader( inFile,inEncode ); 401 PrintWriter writer = FileUtil.getPrintWriter( outFile,outEncode ); 402 403 String line = null; 404 try { 405 int lineNo = 0; 406 while((line = reader.readLine()) != null) { 407 lineNo++ ; 408 if( lineNo >= firstLineNo ) { 409 Matcher mach = pattern.matcher( line ); 410 411 String chnStr = null; 412 if( "CHANGE".equals( insert ) ) { 413 chnStr = strChange( mach ); 414 } 415 else if( "BEFORE".equals( insert ) ) { 416 chnStr = strBefore( line,mach ); 417 } 418 else if( "AFTER".equals( insert ) ) { 419 chnStr = strAfter( line,mach ); 420 } 421 422 if( chnStr != null ) { 423 line = chnStr; 424 cngCount++ ; // 変換されれ? カウン? 425 } 426 } 427 writer.println( line ); // readLine() してる?で、最後に改行が?? 428 } 429 } 430 catch ( IOException ex ) { 431 String errMsg = "処?にエラーが発生しました?" + line + "]" ; 432 throw new RuntimeException( errMsg,ex ); 433 } 434 finally { 435 Closer.ioClose( reader ); 436 Closer.ioClose( writer ); 437 } 438 } 439 /** 440 * キーワードを????に置き換えます? 441 * useBackup 属?に true を指定した?合?置き換え後?、backup ファイルは? 442 * オリジナル_backup と?名称に変わります? 443 * ここでは、ファイルをすべて読み取ってから、チェ?します? 444 * よって、?行にまたが?keyword でのマッチングが可能です? 445 * 446 * @og.rev 4.0.1.0 (2007/12/14) 置換??独立させます? 447 * 448 * @param fileLine 検索??行文字? 449 * @param outFile 出力ファイルオブジェク? 450 */ 451 private void changeKeywordAsBulk( final String fileLine,final File outFile ) { 452 PrintWriter writer = FileUtil.getPrintWriter( outFile,outEncode ); 453 454 String line = fileLine ; 455 try { 456 Matcher mach = pattern.matcher( line ); 457 458 String chnStr = null; 459 if( "CHANGE".equals( insert ) ) { 460 chnStr = strChange( mach ); 461 } 462 else if( "BEFORE".equals( insert ) ) { 463 chnStr = strBefore( line,mach ); 464 } 465 else if( "AFTER".equals( insert ) ) { 466 chnStr = strAfter( line,mach ); 467 } 468 469 if( chnStr != null ) { 470 line = chnStr; 471 cngCount++ ; // 変換されれ? カウン? 472 } 473 474 writer.print( line ); // 注意:改行コード?、不? 475 } 476 catch ( RuntimeException ex ) { 477 String errMsg = "処?にエラーが発生しました?" + outFile.getPath() + "]" ; 478 throw new RuntimeException( errMsg,ex ); 479 } 480 finally { 481 Closer.ioClose( writer ); 482 } 483 } 484 485 /** 486 * insert が?"CHANGE" の場合?処?果を求めます? 487 * 変換しなかった?合?、null を返します? 488 * これは、変換カウントを算?する為のフラグ代わりに使用して?す? 489 * 490 * @param mach キーワード?正規表現 491 * 492 * @return 変換結果(対象行で無??合?、null) 493 */ 494 private String strChange( final Matcher mach ) { 495 String line = null; 496 if( mach.find() ) { 497 line = mach.replaceAll( change ); 498 } 499 return line ; 500 } 501 502 /** 503 * insert が?"BEFORE" の場合?処?果を求めます? 504 * 変換しなかった?合?、null を返します? 505 * これは、変換カウントを算?する為のフラグ代わりに使用して?す? 506 * 507 * @param line 検索? 508 * @param mach キーワード?正規表現 509 * 510 * @return 変換結果(対象行で無??合?、null) 511 */ 512 private String strBefore( final String line , final Matcher mach ) { 513 boolean isChng = false; 514 StringBuilder buf = new StringBuilder( line.length() ); 515 int indx = 0; 516 while( mach.find() ) { 517 isChng = true; 518 int strt = mach.start() + insOffset; 519 buf.append( line.substring( indx,strt ) ); 520 buf.append( change ); 521 indx = strt; 522 } 523 524 String rtn = null; 525 if( isChng ) { 526 buf.append( line.substring( indx ) ); 527 rtn = buf.toString(); 528 } 529 530 return rtn ; 531 } 532 533 /** 534 * insert が?"AFTER" の場合?処?果を求めます? 535 * 変換しなかった?合?、null を返します? 536 * これは、変換カウントを算?する為のフラグ代わりに使用して?す? 537 * 538 * @param line 検索? 539 * @param mach キーワード?正規表現 540 * 541 * @return 変換結果(対象行で無??合?、null) 542 */ 543 private String strAfter( final String line , final Matcher mach ) { 544 boolean isChng = false; 545 StringBuilder buf = new StringBuilder( line.length() ); 546 int indx = 0; 547 while( mach.find() ) { 548 isChng = true; 549 int end = mach.end() + insOffset; 550 buf.append( line.substring( indx,end ) ); 551 buf.append( change ); 552 indx = end; 553 } 554 String rtn = null; 555 if( isChng ) { 556 buf.append( line.substring( indx ) ); 557 rtn = buf.toString(); 558 } 559 560 return rtn ; 561 } 562 563 /** 564 * プロセスの処?果のレポ?ト表現を返します? 565 * 処??ログラ?、?力件数、?力件数などの??です? 566 * こ???をそのまま、標準?力に出すことで、結果レポ?トと出来るよ? 567 * 形式で出してください? 568 * 569 * @return 処?果のレポ?? 570 */ 571 public String report() { 572 if( findCount < cngCount ) { findCount = cngCount; } 573 574 String report = "[" + getClass().getName() + "]" + CR 575 + TAB + "Search Keyword : " + keyword + CR 576 + TAB + "Search File Count : " + inCount + CR 577 + TAB + "Key Find Count : " + findCount + CR 578 + TAB + "Key Change Count : " + cngCount ; 579 580 return report ; 581 } 582 583 /** 584 * こ?クラスの使用方法を返します? 585 * 586 * @return こ?クラスの使用方? 587 */ 588 public String usage() { 589 StringBuilder buf = new StringBuilder(); 590 591 buf.append( "Process_Grep は、上流から受け取っ?FileLineModelから、文字?を見つけ?? ).append( CR ); 592 buf.append( "ChainProcess インターフェースの実?ラスです?" ).append( CR ); 593 buf.append( CR ); 594 buf.append( "正規表現の keyword を上流から受け取っ?FileLineModel から検索します?" ).append( CR ); 595 buf.append( "見つかった対象ファイルから、指定???を置換する?合??change ? ).append( CR ); 596 buf.append( "-changeFile で、keyword を置換する文字?を指定して下さ??" ).append( CR ); 597 buf.append( "置換する文字?には、\t と \n の特殊文字が使用できます?" ).append( CR ); 598 buf.append( CR ); 599 buf.append( "処?象は??常は?行づつ読み取りながら処?行います?存在チェ?の場合?? ).append( CR ); 600 buf.append( "見つかった時点で処?中止します?これは、該当?をピ?ア??するのではなく?" ).append( CR ); 601 buf.append( "存在して?かど?を判断して、あれ?、下流に流すと?のが目?からです?" ).append( CR ); 602 buf.append( "keyword を?改行を含?規表現で、検索・置換する?合??useBulkRead 属?? ).append( CR ); 603 buf.append( "true に設定してください。これ?、?力ファイルを?して読み込みます?" ).append( CR ); 604 buf.append( "-ignoreCase は、検索時にキーの大?小文字を無視するよ??します?" ).append( CR ); 605 buf.append( "-notEquals は、結果(見つかればtrue)を反転(見つからなければtrue)します?" ).append( CR ); 606 buf.append( "これは、行単位ではなく?ファイル単位に判定します?で、change ?した?? ).append( CR ); 607 buf.append( "でも?対象行?、見つかった行です?ただし?下流に対して、見つからな? ).append( CR ); 608 buf.append( "場合だけ??継続させます?" ).append( CR ); 609 buf.append( "-inEncode は、?力ファイルのエンコード指定になります?" ).append( CR ); 610 buf.append( "-outEncode は、?力ファイルのエンコードや、changeFileで??置換文字?" ).append( CR ); 611 buf.append( "ファイルのエンコード指定になります?(changeFile は、? 出力ファイルと)" ).append( CR ); 612 buf.append( "同じエンコードです?" ).append( CR ); 613 buf.append( "これら?エンコードが無??場合?、System.getProperty(\"file.encoding\") " ).append( CR ); 614 buf.append( "で求まる?を使用します?" ).append( CR ); 615 buf.append( "-changeFile を使用することで、?行???に置換することが可能です?" ).append( CR ); 616 buf.append( CR ); 617 buf.append( "上?プロセスチェインの??タは上流から渡されます?)からのLineModel の" ).append( CR ); 618 buf.append( "ファイルオブジェクトより?????が含まれて?か検索します?" ).append( CR ); 619 buf.append( "上流?ロセスでは、Name 属?として、?File』を持ち、?は、Fileオブジェク? ).append( CR ); 620 buf.append( "である、Process_FileSearch を使用するのが?便利です?それ以外?クラス? ).append( CR ); 621 buf.append( "使用する場合でも?Name属?と、File オブジェクトを持つ LineModel を受け渡? ).append( CR ); 622 buf.append( "できれば、使用可能です?" ).append( CR ); 623 buf.append( CR ); 624 buf.append( "引数??中に空白を含??合?、ダブルコー??ション(\"\") で括って下さ??" ).append( CR ); 625 buf.append( "引数??の ?』?前後には、空白は挟めません。??key=value の様に" ).append( CR ); 626 buf.append( "繋げてください? ).append( CR ); 627 buf.append( CR ).append( CR ); 628 629 buf.append( getArgument().usage() ).append( CR ); 630 631 return buf.toString(); 632 } 633 634 /** 635 * こ?クラスは、main メソ?から実行できません? 636 * 637 * @param args コマンド引数配? 638 */ 639 public static void main( final String[] args ) { 640 LogWriter.log( new Process_Grep().usage() ); 641 } 642 }