【发布时间】:2013-01-15 07:25:59
【问题描述】:
我希望我的 perl 程序在所有文件中执行 '{' -> '{function('.counter++.')' 的替换,但当行中有 '{' 和 '}' 时同一行,除非 '{' 出现在 'typedef' 子字符串下的一行。
#!/usr/bin/perl
use strict;
use warnings;
use Tie::File;
use File::Find;
my $dir = "C:/test dir";
# fill up our argument list with file names:
find(sub { if (-f && /\.[hc]$/) { push @ARGV, $File::Find::name } }, $dir);
$^I = ".bak"; # supply backup string to enable in-place edit
my $counter = 0;
# now process our files
while (<>)
{
my @lines;
# copy each line from the text file to the string @lines and add a function call after every '{' '
tie @lines, 'Tie::File', $ARGV or die "Can't read file: $!\n"
foreach (@lines)
{
if (!( index (@lines,'}')!= -1 )) # if there is a '}' in the same line don't add the macro
{
s/{/'{function(' . $counter++ . ')'/ge;
print;
}
}
untie @lines; # free @lines
}
我试图做的是浏览我在我的目录和子目录中找到的@ARGV 中的所有文件,对于每个 *.c 或 *.h 文件,我想逐行检查并检查这一行是否包含“{”。如果是,程序将不会检查是否有 '{' 并且不会进行替换,如果没有,程序将用 '{function('.counter++.');'
很遗憾,这段代码不起作用。我很惭愧地说我试图让它整天工作但仍然没有成功。我认为我的问题是我并没有真正使用搜索'{'但我不明白的行为什么。非常感谢您的帮助。
我还要补充一点,我是在windows环境下工作的。
谢谢!!
编辑:到目前为止,在您的帮助下,这是代码:
use strict;
use warnings;
use File::Find;
my $dir = "C:/projects/SW/fw/phy"; # use forward slashes in paths
# fill up our argument list with file names:
find(sub { if (-f && /\.[hc]$/) { push @ARGV, $File::Find::name } }, $dir);
$^I = ".bak"; # supply backup string to enable in-place edit
my $counter = 0;
# now process our files
while (<>) {
s/{/'{ function(' . $counter++ . ')'/ge unless /}/;
print;
}
剩下要做的就是让它忽略 '{' 替换,当它是 'typedef' 子字符串下的一行时,如下所示:
typedef struct
{
}examp;
非常感谢您的帮助!谢谢! :)
编辑#2:这是最终代码:
use strict;
use warnings;
use File::Find;
my $dir = "C:/exmp";
# fill up our argument list with file names:
find(sub { if (-f && /\.[hc]$/) { push @ARGV, $File::Find::name } }, $dir);
$^I = ".bak"; # supply backup string to enable in-place edit
my $counter = 0;
my $td = 0;
# now process our files
while (<>) {
s/{/'{ function(' . $counter++ . ')'/ge if /{[^}]*$/ && $td == 0;
$td = do { (/typedef/ ? 1 : 0 ) || ( (/=/ ? 1 : 0 ) && (/if/ ? 0 : 1 ) && (/while/ ? 0 : 1 ) && (/for/ ? 0 : 1 ) && (/switch/ ? 0 : 1 ) )};
print;
}
代码执行替换,除非替换位置上方的行包含“typedef”, 当它上面的行包含 '=' 并且没有 'if'、'while'、'for' 或 'switch' 时,替换也不会发生。
感谢大家的帮助!
【问题讨论】:
-
为什么不使用 sed?
sed -e '/{[^}]*$/{s/{/{function('\''.counter++.'\'');/}' -i.bak * -
@squiguy 没有人是完美的! ;-) 完全可以,你也可以使用 perl 来做同样的事情……见我的回答。