0

我有以下文本块(带有 \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 最终未定义。错误是“在 [line "print $text"] 的打印中使用未初始化的值 $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;
}
4

2 回答 2

2

这可能对您有用(GNU sed):

sed ':a;$!{N;ba};s/\n\?<?php\r\?\n\/\*\r\?\n\*\/\r\?\n?>//g' file

这会将整个文件放入模式空间,然后删除所需的字符串。

正则表达式使用\?which 意味着期望 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
于 2013-08-04T08:34:46.863 回答
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在换行符 ( ) 之间重复替换 ( ),因此正则表达式中的空格不重要。mx

匹配模式查找<?php后跟零个或多个空格 ( \s*)、可选的回车 ( \r?) 和换行 ( \n)。空格、回车和换行模式出现 4 次,每行以您要匹配的模式结尾一次。其他部分匹配之前的零个或多个空格,之前/*的零个或多个空格*/,以及之前的零个或多个空格?>,记住*and?是特殊字符,必须转义以匹配它们。

样本输出

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;
}

错误处理还有很多不足之处;thedie可能应该被替换为print(到标准错误)并返回。

于 2013-08-03T20:01:43.263 回答