我有以下文本块(使用\ r \ n或\ n),我想用sed找到并删除它。
<?php
/*
*/
?>
我尝试了很多令人尴尬的事情(根据许多SE答案)来删除那些已经失败的事情,而不是浑水浑浊,捕捉和删除这种模式的正确方法是什么?对\ n或\ r \ n使用两个单独的sed命令也很好。
好的,我会分享两次糟糕的尝试:
sed 'N;s/<\?php\r\n\/\*\r\n\*\/\r\n\?>//g' file.txt
sed ':a;N;$!ba;s/<\?php\r\n\/\*\r\n\*\/\r\n\?>//g' file.txt
编辑:基于下面的答案,我尝试将其置于PERL递归例程中,搜索.php文件并修改它们。但是,$ text最终未定义。错误是“使用未初始化的值$ text打印在[line”print $ text“]”
抱歉,我之前没有使用过perl ...
#!/usr/bin/perl
use strict;
use warnings;
my $parent_dir = ".";
my $dir="";
my $file="";
process_dir($parent_dir);
sub process_dir {
my $dir = shift;
print "Processing $dir\n";
opendir(my $SCR , $dir) or die "Can't open $dir: $!";
while( defined (my $file = readdir $SCR) )
{
next if ($file =~ /\.$/ );
if ( $file =~ /\.php$/ ) {
&process_file();
} elsif ( -d "$dir/$file" ) {
print "directory : $dir/$file\n";
process_dir("$dir/$file/");
#next;
#} elsif ( $file
} else {
print "Else :$file\n" if ( -B "$dir/$file");
}
print "file -> $file\n";
}
closedir($SCR);
}
sub process_file{
my $text="";
open(my $fh, '<', "$dir/$file") or die "cannot open file $file";
{
local $/;
$text = <$fh>;
}
close($fh);
print "Before:\n";
print $text;
$text =~ s{ <\?php \s* \r?\n \s* /\* \s* \r?\n \s* \*/ \s* \r?\n \?> \s* \r?\n }{}gmx;
print "After:\n";
print $text;
}
答案 0 :(得分:2)
这可能适合你(GNU sed):
sed ':a;$!{N;ba};s/\n\?<?php\r\?\n\/\*\r\?\n\*\/\r\?\n?>//g' file
这会将整个文件拖入模式空间,然后删除所需的字符串。
正则表达式使用\?
,这意味着期望1或0的前进模式(在一般情况下为\r
或在第一种情况下为\n
。
白色空间可能是一个看不见的问题,在这种情况下:
sed ':a;$!{N;ba};s/\n\?\s*<?php\s*\r\?\n\s*\/\*\s*\r\?\n\s*\*\/\s*\r\?\n\s*?>//g' file
答案 1 :(得分:1)
我可能会使用Perl来完成这项工作。假设文件足够小以至于将整个文件放入内存是一种合理的策略,那么这段代码似乎可以完成这项工作:
#!/usr/bin/env perl
use strict;
use warnings;
my $text;
{
local $/;
$text = <>;
}
print "Before:\n";
print $text;
$text =~ s{ <\?php \s* \r?\n \s* /\* \s* \r?\n \s* \*/ \s* \r?\n \?> \s* \r?\n }{}gmx;
print "After:\n";
print $text;
前三行是标准启动代码。接下来的五个将整个文件读入变量$text
。印刷线是不言自明的。替代命令是所有乐趣所在。
模式位于第一个{}
对之间;替换文本位于第二对{}
之间。最后的限定符使用扩展符号(g
)跨换行(m
)重复替换(x
),以便正则表达式中的空格不重要。
匹配模式查找<?php
后跟零个或多个空格(\s*
),可选择回车符(\r?
)和换行符(\n
)。空格,回车和换行模式显示4次,每个行以您想要匹配的模式结束。其他部分在/*
之前匹配零个或多个空格,在*/
之前匹配零个或多个空格,在?>
之前匹配零个或多个空格,记住*
和{{1}是特殊字符,必须进行转义才能与字面匹配。
?
Before:
aasdasdsa
sdasdsada
<?php
/*
*/
?>
sdasdasda
asdsdasas
After:
aasdasdsa
sdasdsada
sdasdasda
asdsdasas
错误处理还有很多不足之处; #!/usr/bin/env perl
use strict;
use warnings;
use File::Find;
find({ wanted => \&process_file, no_chdir => 1 }, @ARGV);
sub process_file
{
my $name = $_;
return unless -f $name;
print "$name\n";
open my $fh, '+<', $name or die "Failed to open file $name for reading and writing";
my $text;
{
local $/;
$text = <$fh>;
}
$text =~ s{ <\?php \s* \r?\n \s* /\* \s* \r?\n \s* \*/ \s* \r?\n \?> \s* \r?\n }{}gmx;
seek $fh, 0, 0;
truncate $fh, 0;
print $fh $text;
close $fh;
}
可能应该被die
替换(标准错误)并返回。