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 }