sed换行和回车模式捕获

时间:2013-08-03 19:37:44

标签: sed

我有以下文本块(使用\ 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;
}

2 个答案:

答案 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脚本

我可能会使用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替换(标准错误)并返回。