简体   繁体   中英

how to using Grep for remove the specific end word of line in perl?

I will create a file every day , I want to remove the line that end character is utc and output to other file in perl, I try to use grep an regexp, but get the error msg as below,

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

the grep code :

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

the file loos like

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

Any suggestions? I am more then happy to try anything at this point.

There is no need to go to external tools for such a common task. It involves starting a shell and yet another program, and (doubly) escaping things just right; it is error prone and far less efficient, and inferior in terms of error checking. Why not use Perl in a Perl program?

Read a file and write its lines over to a new file, skipping the ones you don't want. See this post for details, for example.

Here is a quick way using 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);

The module's path($file) opens the file and lines returns the list of lines; they are filtered by grep and those that don't end in utc (with possible trailing space) are assigned to @new_lines .

Then the spew method writes those lines to $new_file .

For a couple of (other) ways to "edit" a file using this module see this post .


In a one-liner

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

A direct answer may best illustrate (some of) the disadvantages of using external commands.

We need to pass to grep , via shell, particular sequences which would be interpreted by either or both Perl and shell; so they need be escaped correctly

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

This works on my system.

First: simple perl

From

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

or as a script:

#!/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;

Or using 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 );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM