my perl script --- Trave Target directory and modify files with regex

脚本用于遍历目录下文件,并用正则表达式匹配替换目标string.

#!/usr/bin/perl -w
use strict;

# Trave Target directory and modify files under it.
# Modified files are matched using regex.
#
# V1.1

use Getopt::Long;

my $usage = q{
Usage: fix_fetch_found [options] [dir]

     Output is write back to files and marked with /*by script begin||end*/.

     options:
        dir             Dir to fix error that fetch and %found is null are out of order
        -?,--help       Display this help message
};

# process the command line

my $help = 0;
my $dirpath = $ARGV[0];

GetOptions(
    'help|?' => \$help,
    ) or die $usage;

if ($help) {
    print $usage;
    exit;
}

# main actions
my $string = get_localtime($dirpath);
my $log = $string.".log";
my $modified_log = $string."_modified.log";
Traversal($dirpath,$log);
open(Log_File,"$log") or die("Could not open '$log' for reading $!");
while(my $name = <Log_File>){
chomp($name);
my $flag = fix_file($name);
if ($flag){
	write_file_a($modified_log,$name."\n");
}
}
close(Log_File);
exit;

# fix file with filename
sub fix_file{
my ($filename) = @_;

my $flag = 0;
my $filedata = read_file($filename);
my $modified_data = modified_content($filedata);
#print "check file $filename...\n";
my $result = check_fix($modified_data,$filename);
if ($result){ 
	write_file_w($filename, $modified_data);
	print "fix file $filename!\n";
	$flag = 1;
}
return $flag;
}

# check whether file is modified
sub check_fix{
my ($file_1,$filename) = @_;

my $result = 1;
my $file_2 = read_file($filename);
if ($file_1 eq $file_2){
	$result = 0;
#	print "$filename is not modified!\n";
}
return $result;
}

# modify file content using regex
sub modified_content{
my($content) = @_;

#match string with /* FETCH VARS GUESSED */
$content =~ s/IF\s*\n*\s*.*%ISOPEN\s*AND\s*\(.*%FOUND\s*IS\s*NULL\s*OR.*%FOUND\n*.*\)\s*THEN\n*\s*\/\* FETCH VARS GUESSED \*\/\s*FETCH\s*([\w_]+)\s*INTO([^;]*);/\/*by script begin*\/fetch $1 into $2;\n             if $1%isopen and $1%found then\/*by script end*\//gi;

#match string without /* FETCH VARS GUESSED */
$content =~ s/IF\s*\n*\s*.*%ISOPEN\s*AND\s*\(.*%FOUND\s*IS\s*NULL\s*OR.*%FOUND\n*.*\)\s*THEN\n*\s*FETCH\s*([\w_]+)\s*INTO([^;]*);/\/*by script begin*\/fetch $1 into $2;\n             if $1%isopen and $1%found then\/*by script end*\//gi;

return $content;
}

# Trave dir and write all file path into a log
sub Traversal{
	my ($path,$file) = @_;
	my $subpath;
	my $handle;
	my $record;
if(-d $path){
	if(opendir($handle,$path)){
		while($subpath = readdir($handle)){
		if(!($subpath =~ m/^\.$/) and !($subpath =~ m/^(\.\.)$/)){
			my $p = $path."/$subpath";
			if (-d $p){
				Traversal($p,$file);
				}
			else{
				open($record,">>$file")||die("Could not open '$file' for writing $!");
				print $record($p."\n");
				close($record);
				} 
			}
		}
	}
	closedir($handle);
}
return;
}

# get local time and append a string for file name
sub get_localtime{
my ($path) =@_;

(my $sec,my $min,my $hour,my $day,my $mon,my $year,my $wday,my $yday,my $isdst)=localtime(time());
$year+=1900;
$mon+=1;
my $time = join("_",$year,$mon,$day,$hour,$min,$sec);
my $str = $path."_".$time;
return $str;
}

# read file
sub read_file {
my ($filename) = @_;
  
open my $in, '<', $filename or die "Could not open '$filename' for reading $!";
local $/ = undef;
# local $/ = undef can read all content into a variable

my $all = <$in>;
close $in;
  
return $all;
}

# write file w
sub write_file_w {
my ($filename, $content) = @_;
  
open my $out, '>', $filename or die "Could not open '$filename' for writing $!";
print $out $content;
close $out;
  
return;
}

# write file a
sub write_file_a{
my ($filename,$line) = @_;

open (my $out,">>$filename") or die "Could not open '$filename' for writing $!";
print $out $line;
close $out;

return;
}

 注:1. 代码中的readfile 中local $/ = undef; 可以读取全文放入一个变量(将$/ 设置为undef,\n 不再表示换行符)

  2.上面的遍历目录方法还可以用 File::Find library 实现,代码如下:

  此处$file_1为文件名,$file= $File::Find::name;为文件path。

#!/usr/bin/perl -w
use strict;
 
use File::Find;
 
my $dir = $ARGV[0];
my @filespath;
my @filesname;

find (\&trave,$dir);

exit;
 
sub trave{
    my $file_1 = $_;
    my $file = $File::Find::name;
    if (-f $file_1){
    print ($file."\n");
    push @filespath ,$file;
    push @filesname ,$file_1;
}
}

 

你可能感兴趣的:(my perl script --- Trave Target directory and modify files with regex)