Earlier today I wanted to edit a lot of source code to add some Emacs hints about the tab stop. I originally wrote it in perl and it works fine, takes two seconds to edit 150MB of text across 4851 files.
time find . -type f -print0 | xargs -0 /opt/perl-5.10.0/bin/perl tab-width
real 0m1.966s user 0m1.340s sys 0m0.354s
undef $/; my $RX = qr/ (?^(? .*)Local\ variables:.*\n ) (? (?: \k .*\n )* ) (? \k End: ) /mix;
for my $fn ( @ARGV ) { next if $fn =~ m{/.git};
open my $fh, '+<', $fn or die "Can't open $fn: $!"; binmode $fh or die $!;
my $src = <$fh>; next unless $src =~ s{$RX}{$+{start}$+{variables}$+{indent}tab-width: 8\n$+{end}};
seek $fh, 0, 0 or die $!; truncate $fh, 0 or die $!; print { $fh } $src or die $!; close $fh or die "Can't close $fh: $!"; }
time find . -type f -print0 | xargs -0 /opt/ruby-1.8.6/bin/ruby tab-width.rb real 31m19.763s user 18m7.957s sys 12m5.596s
RX = Regexp.new( " ( ^(.*)Local\\ variables:.*\\n ) ( ( \\2.*\\n )* ) ( \\2End: )", Regexp::EXTENDED | Regexp::MULTILINE )
ARGV.each do |fn| next if fn =~ %r{/\.git}
open( fn, 'r+' ) do |fh| fh.binmode
src = fh.read next unless src.sub!( RX ) {|m| "#{$1}#{$3}#{$2}tab-width: 8\n#{$5}" }
fh.seek 0, IO::SEEK_SET fh.truncate 0 fh.puts src end end