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 }