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 *
237 * @param data オリジナルのLineModel
238 *
239 * @return 処?換後?LineModel
240 */
241 public LineModel action( final LineModel data ) {
242 inCount++ ;
243
244 final FileLineModel fileData ;
245 if( data instanceof FileLineModel ) {
246 fileData = (FileLineModel)data ;
247 }
248 else {
249 String errMsg = "??タ?FileLineModel オブジェクトではありません? + CR ;
250 throw new RuntimeException( errMsg );
251 }
252
253 File file = fileData.getFile() ;
254 if( ! file.isFile() ) {
255 if( display ) { println( data.dataLine() ); } // 5.1.2.0 (2010/01/01) display の条件変更
256 return data;
257 }
258
259 final boolean isFind ;
260 try {
261 String fileLine = null;
262 int firstLineNo = -1;
263 if( useBulkRead ) { fileLine = findKeywordAsBulk( file ); }
264 else { firstLineNo = findKeyword( file ); }
265
266 isFind = ( fileLine != null ) || ( firstLineNo >= 0 ) ;
267
268 // 置換??ただし?見つかったとき?み実?
269 if( change != null && isFind ) {
270 // 入力ファイルは、オリジナル_backup ファイルとする。過去のファイルを削除
271 File inFile = new File( file.getPath() + "_backup" );
272 if( inFile.exists() && !inFile.delete() ) {
273 String errMsg = "??ファイルを削除できませんでした?" + inFile + "]" ;
274 throw new RuntimeException( errMsg );
275 }
276
277 // オリジナルのファイルを?_backup ファイル名に先に変換する?
278 File fromFile = new File( file.getPath() );
279 if( !fromFile.renameTo( inFile ) ) {
280 String errMsg = "??ファイルをリネ??きませんでした?" + fromFile + "]" ;
281 throw new RuntimeException( errMsg );
282 }
283
284 // 変換処?本?
285 if( useBulkRead ) { changeKeywordAsBulk( fileLine,file ); }
286 else { changeKeyword( inFile,file,firstLineNo ); }
287
288 // backup を使わな??合?、削除する?
289 // 4.0.0.0 (2007/11/29) 入れ子if の統?
290 if( ! useBackup && !inFile.delete() ) {
291 String errMsg = "??ファイルを削除できませんでした?" + inFile + "]" ;
292 throw new RuntimeException( errMsg );
293 }
294 }
295 }
296 catch ( RuntimeException ex ) {
297 String errMsg = "処?にエラーが発生しました?"
298 + data.getRowNo() + "]件目" + CR
299 + data.toString() ;
300 throw new RuntimeException( errMsg,ex );
301 }
302
303 if( display && ( notEquals ^ isFind ) ) { println( data.dataLine() ); } // 5.1.2.0 (2010/01/01) display の条件変更
304 return ( notEquals ^ isFind ) ? data : null ;
305 }
306
307 /**
308 * キーワードが存在して?かど?をチェ?します?
309 * ここでは?行づつ読み取りながら、最初に見つかった時点で制御を返します?
310 * よって、?行にまたが?keyword でのマッチングは出来ませんが?大きな
311 * ファイル等での検索には、効?です?
312 *
313 * @og.rev 4.0.1.0 (2007/12/14) 新規追?
314 *
315 * @param file 検索??ファイルオブジェク?
316 *
317 * @return ??に見つかった行番号(見つからなければ?1 を返す)
318 */
319 private int findKeyword( final File file ) {
320 BufferedReader reader = null;
321
322 int firstLineNo = -1;
323 try {
324 reader = FileUtil.getBufferedReader( file,inEncode );
325 String line ;
326 int lineNo = 0;
327 while((line = reader.readLine()) != null) {
328 lineNo++ ;
329 Matcher mach = pattern.matcher( line );
330 if( mach.find() ) {
331 if( debug ) {
332 String buf = "DEBUG:\t" + file.getPath() + "(" + lineNo + "): " + line ;
333 println( buf );
334 }
335 firstLineNo = lineNo;
336 break;
337 }
338 }
339 }
340 catch ( IOException ex ) {
341 String errMsg = "ファイル読取エラーが発生しました?" + file.getPath() + "]" ;
342 throw new RuntimeException( errMsg,ex );
343 }
344 finally {
345 Closer.ioClose( reader );
346 }
347
348 return firstLineNo;
349 }
350
351 /**
352 * キーワードが存在して?かど?をチェ?します?
353 * ここでは、ファイルをすべて読み取ってから、チェ?します?
354 * よって、?行にまたが?keyword でのマッチングが可能です?
355 *
356 * @og.rev 4.0.1.0 (2007/12/14) 新規追?
357 *
358 * @param file 検索??ファイルオブジェク?
359 *
360 * @return 検索??ファイルの??化情報(ただし?見つからなければ、null)
361 */
362 private String findKeywordAsBulk( final File file ) {
363
364 boolean isFind = false;
365
366 FileString sf = new FileString();
367 sf.setFilename( file.getPath() );
368 sf.setEncode( inEncode );
369 String line = sf.getValue();
370
371 Matcher mach = pattern.matcher( line );
372 if( mach.find() ) {
373 if( debug ) { println( "DEBUG:\t" + file.getPath() ); }
374 isFind = true;
375 }
376
377 return ( isFind ) ? line : null;
378 }
379
380 /**
381 * キーワードを????に置き換えます?
382 * useBackup 属?に true を指定した?合?置き換え後?、backup ファイルは?
383 * オリジナル_backup と?名称に変わります?
384 * ここでは?行づつ読み取りながら、変換処?行います?
385 * よって、?行にまたが?keyword でのマッチングは出来ませんが?大きな
386 * ファイル等での置換でも?メモリの使用量?抑えられます?
387 *
388 * @og.rev 4.0.1.0 (2007/12/14) 置換??独立させます?
389 *
390 * @param inFile 検索??入力ファイルオブジェク?
391 * @param outFile 変換後?出力ファイルオブジェク?
392 * @param firstLineNo キーワードが存在した場合???の行番号
393 */
394 private void changeKeyword( final File inFile,final File outFile,final int firstLineNo ) {
395
396 BufferedReader reader = FileUtil.getBufferedReader( inFile,inEncode );
397 PrintWriter writer = FileUtil.getPrintWriter( outFile,outEncode );
398
399 String line = null;
400 try {
401 int lineNo = 0;
402 while((line = reader.readLine()) != null) {
403 lineNo++ ;
404 if( lineNo >= firstLineNo ) {
405 Matcher mach = pattern.matcher( line );
406
407 String chnStr = null;
408 if( "CHANGE".equals( insert ) ) {
409 chnStr = strChange( mach );
410 }
411 else if( "BEFORE".equals( insert ) ) {
412 chnStr = strBefore( line,mach );
413 }
414 else if( "AFTER".equals( insert ) ) {
415 chnStr = strAfter( line,mach );
416 }
417
418 if( chnStr != null ) {
419 line = chnStr;
420 cngCount++ ; // 変換されれ? カウン?
421 }
422 }
423 writer.println( line ); // readLine() してる?で、最後に改行が??
424 }
425 }
426 catch ( IOException ex ) {
427 String errMsg = "処?にエラーが発生しました?" + line + "]" ;
428 throw new RuntimeException( errMsg,ex );
429 }
430 finally {
431 Closer.ioClose( reader );
432 Closer.ioClose( writer );
433 }
434 }
435 /**
436 * キーワードを????に置き換えます?
437 * useBackup 属?に true を指定した?合?置き換え後?、backup ファイルは?
438 * オリジナル_backup と?名称に変わります?
439 * ここでは、ファイルをすべて読み取ってから、チェ?します?
440 * よって、?行にまたが?keyword でのマッチングが可能です?
441 *
442 * @og.rev 4.0.1.0 (2007/12/14) 置換??独立させます?
443 *
444 * @param fileLine 検索??行文字?
445 * @param outFile 出力ファイルオブジェク?
446 */
447 private void changeKeywordAsBulk( final String fileLine,final File outFile ) {
448 PrintWriter writer = FileUtil.getPrintWriter( outFile,outEncode );
449
450 String line = fileLine ;
451 try {
452 Matcher mach = pattern.matcher( line );
453
454 String chnStr = null;
455 if( "CHANGE".equals( insert ) ) {
456 chnStr = strChange( mach );
457 }
458 else if( "BEFORE".equals( insert ) ) {
459 chnStr = strBefore( line,mach );
460 }
461 else if( "AFTER".equals( insert ) ) {
462 chnStr = strAfter( line,mach );
463 }
464
465 if( chnStr != null ) {
466 line = chnStr;
467 cngCount++ ; // 変換されれ? カウン?
468 }
469
470 writer.print( line ); // 注意:改行コード?、不?
471 }
472 catch ( RuntimeException ex ) {
473 String errMsg = "処?にエラーが発生しました?" + outFile.getPath() + "]" ;
474 throw new RuntimeException( errMsg,ex );
475 }
476 finally {
477 Closer.ioClose( writer );
478 }
479 }
480
481 /**
482 * insert が?"CHANGE" の場合?処?果を求めます?
483 * 変換しなかった?合?、null を返します?
484 * これは、変換カウントを算?する為のフラグ代わりに使用して?す?
485 *
486 * @param mach キーワード?正規表現
487 *
488 * @return 変換結果(対象行で無??合?、null)
489 */
490 private String strChange( final Matcher mach ) {
491 String line = null;
492 if( mach.find() ) {
493 line = mach.replaceAll( change );
494 }
495 return line ;
496 }
497
498 /**
499 * insert が?"BEFORE" の場合?処?果を求めます?
500 * 変換しなかった?合?、null を返します?
501 * これは、変換カウントを算?する為のフラグ代わりに使用して?す?
502 *
503 * @param line 検索?
504 * @param mach キーワード?正規表現
505 *
506 * @return 変換結果(対象行で無??合?、null)
507 */
508 private String strBefore( final String line , final Matcher mach ) {
509 boolean isChng = false;
510 StringBuilder buf = new StringBuilder( line.length() );
511 int indx = 0;
512 while( mach.find() ) {
513 isChng = true;
514 int strt = mach.start() + insOffset;
515 buf.append( line.substring( indx,strt ) );
516 buf.append( change );
517 indx = strt;
518 }
519
520 String rtn = null;
521 if( isChng ) {
522 buf.append( line.substring( indx ) );
523 rtn = buf.toString();
524 }
525
526 return rtn ;
527 }
528
529 /**
530 * insert が?"AFTER" の場合?処?果を求めます?
531 * 変換しなかった?合?、null を返します?
532 * これは、変換カウントを算?する為のフラグ代わりに使用して?す?
533 *
534 * @param line 検索?
535 * @param mach キーワード?正規表現
536 *
537 * @return 変換結果(対象行で無??合?、null)
538 */
539 private String strAfter( final String line , final Matcher mach ) {
540 boolean isChng = false;
541 StringBuilder buf = new StringBuilder( line.length() );
542 int indx = 0;
543 while( mach.find() ) {
544 isChng = true;
545 int end = mach.end() + insOffset;
546 buf.append( line.substring( indx,end ) );
547 buf.append( change );
548 indx = end;
549 }
550 String rtn = null;
551 if( isChng ) {
552 buf.append( line.substring( indx ) );
553 rtn = buf.toString();
554 }
555
556 return rtn ;
557 }
558
559 /**
560 * プロセスの処?果のレポ?ト表現を返します?
561 * 処??ログラ?、?力件数、?力件数などの??です?
562 * こ???をそのまま、標準?力に出すことで、結果レポ?トと出来るよ?
563 * 形式で出してください?
564 *
565 * @return 処?果のレポ??
566 */
567 public String report() {
568 if( findCount < cngCount ) { findCount = cngCount; }
569
570 String report = "[" + getClass().getName() + "]" + CR
571 + TAB + "Search Keyword : " + keyword + CR
572 + TAB + "Search File Count : " + inCount + CR
573 + TAB + "Key Find Count : " + findCount + CR
574 + TAB + "Key Change Count : " + cngCount ;
575
576 return report ;
577 }
578
579 /**
580 * こ?クラスの使用方法を返します?
581 *
582 * @return こ?クラスの使用方?
583 */
584 public String usage() {
585 StringBuilder buf = new StringBuilder();
586
587 buf.append( "Process_Grep は、上流から受け取っ?FileLineModelから、文字?を見つけ?? ).append( CR );
588 buf.append( "ChainProcess インターフェースの実?ラスです?" ).append( CR );
589 buf.append( CR );
590 buf.append( "正規表現の keyword を上流から受け取っ?FileLineModel から検索します?" ).append( CR );
591 buf.append( "見つかった対象ファイルから、指定???を置換する?合??change ? ).append( CR );
592 buf.append( "-changeFile で、keyword を置換する文字?を指定して下さ??" ).append( CR );
593 buf.append( "置換する文字?には、\t と \n の特殊文字が使用できます?" ).append( CR );
594 buf.append( CR );
595 buf.append( "処?象は??常は?行づつ読み取りながら処?行います?存在チェ?の場合?? ).append( CR );
596 buf.append( "見つかった時点で処?中止します?これは、該当?をピ?ア??するのではなく?" ).append( CR );
597 buf.append( "存在して?かど?を判断して、あれ?、下流に流すと?のが目?からです?" ).append( CR );
598 buf.append( "keyword を?改行を含?規表現で、検索・置換する?合??useBulkRead 属?? ).append( CR );
599 buf.append( "true に設定してください。これ?、?力ファイルを?して読み込みます?" ).append( CR );
600 buf.append( "-ignoreCase は、検索時にキーの大?小文字を無視するよ??します?" ).append( CR );
601 buf.append( "-notEquals は、結果(見つかればtrue)を反転(見つからなければtrue)します?" ).append( CR );
602 buf.append( "これは、行単位ではなく?ファイル単位に判定します?で、change ?した?? ).append( CR );
603 buf.append( "でも?対象行?、見つかった行です?ただし?下流に対して、見つからな? ).append( CR );
604 buf.append( "場合だけ??継続させます?" ).append( CR );
605 buf.append( "-inEncode は、?力ファイルのエンコード指定になります?" ).append( CR );
606 buf.append( "-outEncode は、?力ファイルのエンコードや、changeFileで??置換文字?" ).append( CR );
607 buf.append( "ファイルのエンコード指定になります?(changeFile は、? 出力ファイルと)" ).append( CR );
608 buf.append( "同じエンコードです?" ).append( CR );
609 buf.append( "これら?エンコードが無??場合?、System.getProperty(\"file.encoding\") " ).append( CR );
610 buf.append( "で求まる?を使用します?" ).append( CR );
611 buf.append( "-changeFile を使用することで、?行???に置換することが可能です?" ).append( CR );
612 buf.append( CR );
613 buf.append( "上?プロセスチェインの??タは上流から渡されます?)からのLineModel の" ).append( CR );
614 buf.append( "ファイルオブジェクトより?????が含まれて?か検索します?" ).append( CR );
615 buf.append( "上流?ロセスでは、Name 属?として、?File』を持ち、?は、Fileオブジェク? ).append( CR );
616 buf.append( "である、Process_FileSearch を使用するのが?便利です?それ以外?クラス? ).append( CR );
617 buf.append( "使用する場合でも?Name属?と、File オブジェクトを持つ LineModel を受け渡? ).append( CR );
618 buf.append( "できれば、使用可能です?" ).append( CR );
619 buf.append( CR );
620 buf.append( "引数??中に空白を含??合?、ダブルコー??ション(\"\") で括って下さ??" ).append( CR );
621 buf.append( "引数??の ?』?前後には、空白は挟めません。??key=value の様に" ).append( CR );
622 buf.append( "繋げてください? ).append( CR );
623 buf.append( CR ).append( CR );
624
625 buf.append( getArgument().usage() ).append( CR );
626
627 return buf.toString();
628 }
629
630 /**
631 * こ?クラスは、main メソ?から実行できません?
632 *
633 * @param args コマンド引数配?
634 */
635 public static void main( final String[] args ) {
636 LogWriter.log( new Process_Grep().usage() );
637 }
638 }