如何使用Grep删除perl中特定的行结束字?

时间:2017-11-10 08:04:56

标签: regex perl grep

我每天都会创建一个文件,我想删除末尾字符为utc的行并输出到perl中的其他文件, 我尝试使用grep和正则表达式, 但是得到如下错误消息,

sh: -c: line 0: unexpected EOF while looking for matching `"'
sh: -c: line 1: syntax error: unexpected end of file

grep代码:

system("grep -v \"utc$ \" /doc/$date/before > /doc/$date/after");

文件就像

一样松散
config setting
^MMon Nov 13 10:45:52.401 utc   -->the line is I wnat to remove
start configuration...
clock timezone utc 8

有什么建议吗?我现在更乐意尝试任何事情。

2 个答案:

答案 0 :(得分:3)

没有需要使用外部工具来执行此类常见任务。它涉及启动一个shell和另一个程序,并且(加倍地)逃避正确的事情;它容易出错且效率低得多,而且在错误检查方面也较差。为什么不在Perl程序中使用Perl?

读取文件并将其行写入新文件,跳过您不想要的文件。有关详细信息,请参阅this post

以下是使用Path::Tiny

的快捷方式
use warnings;
use strict;

use Path::Tiny;

my $file     = '...';
my $new_file = '...';

my @new_lines = grep { not /utc\s*$/ } path($file)->lines; 

path($new_file)->spew(@new_lines);

模块path($file)打开文件,lines返回行列表;它们按grep进行过滤,不会以utc结尾(可能有尾随空格)的内容会分配到@new_lines

然后spew方法将这些行写入$new_file

有几种(其他)方式来编辑"使用此模块的文件请参阅this post

单行

perl -ne'print if not /utc\s*$/' file  > new_file

直接回答可能最好地说明(某些)使用外部命令的缺点。

我们需要通过shell传递给grep特定序列,这些序列将由Perl和shell之一或两者解释;所以他们需要正确转义

system("grep -v 'utc\\s*\$' $old_file > $new_file");

这适用于我的系统。

答案 1 :(得分:0)

首先:简单的perl

来自

perl -e 'opendir DH,"/doc";foreach my $date (readdir DH) {
   if (-f "/doc/".$date."/before") { open RH,"</doc/".$date."/before";
     open WH,">/doc/".$date."/after";while(<RH>){print WH $_ unless /utc$/;};};
   close RH;close WH;};closedir DH;'

或作为剧本:

#!/usr/bin/perl -w

my $docPath="/doc";
opendir DH,$docPath;
foreach my $date (readdir DH) {
    if (-f $docPath."/".$date."/before") {
        open RH,"<".$docPath."/".$date."/before";
        open WH,">".$docPath."/".$date."/after";
        while(<RH>){
            print WH $_ unless /utc$/;
        };
    };
    close RH;
    close WH;
};
closedir DH;

或使用Path::Tiny

#!/usr/bin/perl -w

use Path::Tiny;

my $docPath=path("/doc");

foreach my $date ($docPath->children) {
    $date->child("after")->spew(
    grep {!/utc$/} $date->child("before")->lines );
}