1- class FileEdit
1+ require 'ftools'
2+ require 'fileutils'
3+ require 'tempfile'
24
3- require 'ftools'
5+ class FileEdit
46
57 private
6- attr_accessor :filename , :contents , :match
8+
9+ attr_accessor :original_pathname , :contents , :file_edited
710
811 public
912
1013 def initialize ( filepath )
11- @filename = filepath
12- @match = false
13-
14- raise ArgumentError , "File doesn't exist" unless File . exist? @filename
15- raise ArgumentError , "File is blank" unless ( @contents = File . new ( @filename ) . readlines ) . length > 0
14+ @original_pathname = filepath
15+ @file_edited = false
1616
17+ raise ArgumentError , "File doesn't exist" unless File . exist? @original_pathname
18+ raise ArgumentError , "File is blank" unless ( @contents = File . new ( @original_pathname ) . readlines ) . length > 0
1719 end
1820
1921 #search the file line by line and match each line with the given regex
@@ -48,17 +50,21 @@ def insert_line_after_match(regex, newline)
4850
4951 #Make a copy of old_file and write new file out (only if file changed)
5052 def write_file
51- # @match is false when there is no match in the whole file. Nothing need to be done.
52- if @match == true
53- File . copy ( @filename , @filename + ".old" )
54- newfile = File . new ( "temp" , "w" )
55- @contents . each ( ) do |line |
56- newfile . puts ( line )
53+
54+ # file_edited is false when there was no match in the whole file and thus no contents have changed.
55+ if file_edited
56+ backup_pathname = original_pathname + ".old"
57+ File . copy ( original_pathname , backup_pathname )
58+ Tempfile . open ( "w" ) do |newfile |
59+ contents . each do |line |
60+ newfile . puts ( line )
61+ end
62+ newfile . flush
63+ FileUtils . mv ( newfile . path , original_pathname )
5764 end
58- newfile . close
59- File . rename ( "temp" , @filename )
6065 end
61- @match = false
66+ self . file_edited = false
67+
6268 end
6369
6470 private
@@ -67,39 +73,39 @@ def write_file
6773 #command is the switch of delete, replace, and insert ('d', 'r', 'i')
6874 #method is to control operation on whole line or only the match (1 for line, 2 for match)
6975 def search_match ( regex , replace , command , method )
70-
76+
7177 #check if regex is Regexp object or simple string and store the Regexp object in exp.
72- ( regex . kind_of? Regexp ) ? exp = regex : exp = Regexp . new ( regex )
78+ exp = ( regex . respond_to? ( :gsub! ) ? regex : Regexp . new ( regex . to_s ) )
7379
74- #loop through @ contents and do the appropriate operation depending on 'command' and 'method'
75- i = 0
76- begin
77- line = @contents [ i ]
78- if line =~ exp
79- @match = true
80+ #loop through contents and do the appropriate operation depending on 'command' and 'method'
81+ new_contents = [ ]
82+
83+ contents . each do | line |
84+ if exp . match ( line ) # =~ exp
85+ self . file_edited = true
8086 case
8187 when command == 'r'
82- ( method == 1 ) ? @contents [ i ] = replace : @contents [ i ] . gsub! ( exp , replace )
88+ new_contents << ( ( method == 1 ) ? replace : line . gsub! ( exp , replace ) )
8389 when command == 'd'
84- if method == 1
85- @contents . delete_at ( i )
86- i = i - 1
87- else
88- @contents [ i ] . gsub! ( exp , "" )
90+ if method == 2
91+ new_contents << line . gsub! ( exp , "" )
8992 end
9093 when command == 'i'
91- @contents . insert ( i +1 , replace )
94+ new_contents << line
95+ new_contents << replace
9296 end
97+ else
98+ new_contents << line
9399 end
94- i = i +1
95- end until i == @contents . length
100+ end
101+
102+ self . contents = new_contents
96103 end
97104end
98105
99106#test
100107if __FILE__ == $0
101108 fedit = FileEdit . new ( "test" )
102-
103109 fedit . insert_line_after_match ( /test/ , "new Line Inserted" )
104110 fedit . search_file_replace ( /test/ , "replace" )
105111 fedit . search_file_replace_line ( /replace/ , "this line is replaced" )
0 commit comments