【问题标题】:how to using Grep for remove the specific end word of line in perl?如何使用 Grep 删除 perl 中行的特定结束词?
【发布时间】:2017-11-13 16:09:24
【问题描述】:

我将每天创建一个文件,我想删除结束字符为 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

有什么建议吗?在这一点上,我更乐意尝试任何事情。

【问题讨论】:

  • 会得到"/doc/是一个目录,它不能得到变量$date
  • 你想做什么?What's must contain $date` 变量?这个变量将设置在哪里? "utc$ "(符号美元后跟空格)是什么意思?
  • 您的文件、路径如何命名?请发布路径示例,也许还有内容!
  • 因为我每天都会创建一个文件,所以日期是一个变量
  • 路径是 /doc/$date/before ,$date 是一个变量

标签: regex perl grep


【解决方案1】:

没有需要使用外部工具来完成这样的常见任务。它涉及启动一个 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");

这适用于我的系统。

【讨论】:

  • 我认为使用-p 标志会更好。 perl -pe 'next if m/utc$/' file 应该可以解决问题。
  • @Sobrique 嗯? next 这里的目的是什么?我认为-p always 会打印该行并且没有办法阻止它。我错了吗?
  • -p 只是插入一个打印$_continue 块。这可以被next之类的循环控制语句绕过。
  • @Sobrique 对我不起作用。 continue docs“因此它可以用来增加循环变量,即使循环已经通过下一条语句继续”。对我来说,这听起来像是 continue 块总是被执行。
  • 嗯,好的。我站得更正了。我明显是糊涂了。我会去回顾一下,因为我至少相当确定-p 有一个“跳过”选项。我会去尝试弄清楚它是什么。
【解决方案2】:

第一:简单的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 );
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    • 2012-08-01
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多