如何用perl 删除文件中的一段内容(多个行)

自行车丢了 发布于 2011/08/04 21:37
阅读 9K+
收藏 0

问一个perl删除多行的问题,具体要求如下:

使用perl删除文件中的多行,举例,有一个文件内容如下:

#===== Custom1 =====
[home_test]
    path = /home/test
    read only = no
    comment = backup home directory (requires authentication)
    auth users = abc
    exclude = test
#===== Custom2 =====
[home_test123]
    path = /home/test123
    read only = no
    comment = backup home directory (requires authentication)
    auth users = abc
    exclude = test
期望的效果:只删除下面的这一段,保留剩下的行。

#===== Custom1 =====
[home_test]
    path = /home/test
    read only = no
    comment = backup home directory (requires authentication)
    auth users = abc
    exclude = test

请高手指教,如何实现?

加载中
0
redraiment
redraiment

呃,下面是一段 Perl 代码,功能和上面一样。文件名以命令行参数形式给出:

#!/usr/bin/perl

for my $file (@ARGV) {
    my $content;

    open(in, "$file");
    $content .= $_ while <in>;
    close(in);

    if ($content =~ s/#=[^\[]*\[home_test\][^#]*//gm) {
        print "$content";
    }
}
0
风林火山
风林火山

1.打开文件,2.读取文件到数组 3.修改数组 4.将数组覆盖原文件(方法是个“笨方法”,但是个好方法。严重怀疑这不是你要的。。。。。 坐等看楼下的好方法!)

0
foxhackd
foxhackd
貌似这个有点像window的INI文件,用perl 操作INI的库应该是很容易的
0
自行车丢了
自行车丢了
我想到的算法是,找到匹配[home_test]的行,然后记录行号,再依次删除包括该行号及其下面的几行。但我现在可以取到匹配[home_test]的行号,可是不知道怎么将行号再替换成内容,没法做删除动作。
0
自行车丢了
自行车丢了

引用来自“风林火山”的答案

1.打开文件,2.读取文件到数组 3.修改数组 4.将数组覆盖原文件(方法是个“笨方法”,但是个好方法。严重怀疑这不是你要的。。。。。 坐等看楼下的好方法!)

呵呵,读到数组的方法不是很好,要删除的内容多的时候就慢了。
0
redraiment
redraiment

需求有些不明确的地方:

  1. 你要处理的所有文里,每个都只有两组数据?
  2. 你只是想删除最后一组数据?
  3. 元素是否固定只有 5 行?
  4. 还是说只是想删除 Custom 2 这一组数据,并且它有可能在文件中间?

如果真的像上面描述的,Custom 2 这组总是在文件最后,且固定只有 7 行数据,那不然用 sed '/Custom 2/,$d' 来删除好了。

0
自行车丢了
自行车丢了

引用来自“redraiment”的答案

需求有些不明确的地方:

  1. 你要处理的所有文里,每个都只有两组数据?
  2. 你只是想删除最后一组数据?
  3. 元素是否固定只有 5 行?
  4. 还是说只是想删除 Custom 2 这一组数据,并且它有可能在文件中间?

如果真的像上面描述的,Custom 2 这组总是在文件最后,且固定只有 7 行数据,那不然用 sed '/Custom 2/,$d' 来删除好了。

我的需求可能还不是很明确,我在补充一下:

1)文件都是一个段落一个段落的,每段内容,除了开头#===部分和[home_test]部分不同以外,其他内容都相同。这一点就是难以直接使用/.../通过匹配来删除的原因。

2)我只想删除匹配[home_test]开头的那个段落,保留其他的段落,文件中这样的段落会有很多,但[home_test]开头的段落只有一处,是唯一的。

0
jobell
jobell
用正则式来做,直接换掉就可以了呀。以[home_test]开头,以下一个[.*]结尾,然后全部用空替换掉。
0
redraiment
redraiment

如果需求仅是删除[home_test]这一段的话,那用 awk 就能完成了:

BEGIN {
    FS = OFS = "\n";
    RS = "#";
}

NF && $2 != "[home_test]" {
    printf "#%s", $0
}

测试数据:

#===== Custom0 =====
[home_test]
    path = /home/test
    read only = no
    comment = backup home directory (requires authentication)
    auth users = abc
    exclude = test
#===== Custom3 =====
[home_test1]
    path = /home/test123
    read only = no
    comment = backup home directory (requires authentication)
    auth users = abc
    exclude = test
#===== Custom1 =====
[home_test]
    path = /home/test
    read only = no
    comment = backup home directory (requires authentication)
    auth users = abc
    exclude = test
#===== Custom2 =====
[home_test123]
    path = /home/test123
    read only = no
    comment = backup home directory (requires authentication)
    auth users = abc
    exclude = test
#===== Custom4 =====
[home_test]
    path = /home/test123
    read only = no
    comment = backup home directory (requires authentication)
    auth users = abc
    exclude = test

执行结果:

$ awk -f multi-line.awk data
#===== Custom3 =====
[home_test1]
    path = /home/test123
    read only = no
    comment = backup home directory (requires authentication)
    auth users = abc
    exclude = test
#===== Custom2 =====
[home_test123]
    path = /home/test123
    read only = no
    comment = backup home directory (requires authentication)
    auth users = abc
    exclude = test
0
自行车丢了
自行车丢了

引用来自“redraiment”的答案

呃,下面是一段 Perl 代码,功能和上面一样。文件名以命令行参数形式给出:

#!/usr/bin/perl

for my $file (@ARGV) {
    my $content;

    open(in, "$file");
    $content .= $_ while <in>;
    close(in);

    if ($content =~ s/#=[^\[]*\[home_test\][^#]*//gm) {
        print "$content";
    }
}

redraiment给出的代码很好用,之前我一直没搞懂s///替换中的m怎么用,你理解的比较好。

不过将所有文件内容都保存在$content变量中,是否内容过多了,

功能还是满足要求了,感谢你及楼上回帖的各位兄台。

返回顶部
顶部