【问题标题】:perl script to copy file content which is between certain linesperl 脚本复制某些行之间的文件内容
【发布时间】:2016-12-23 13:01:53
【问题描述】:

我是 perl 脚本的新手,需要有关给定问题的帮助。 我有许多包含人员详细信息的文件。 我想在特定行之后和特定行之前打印每个文件的内容。 示例:(其中一个文件包含以下详细信息:)

My name is XYZ.
Address: ***
ID:12414
Country:USA
End XYZ

另一个文件包含以下详细信息:

My name is ABC.
Address: ###
ID:124344
Country:Singapore
End ABC

我想将My name is XYZ 之后和End XYZ 之前的第一个文件中的行打印到我的新文件中。同样,我想将My name is ABC 之后和End ABC 之前的第二个文件中的内容打印到我的新文件中。

我编写了如下逻辑,但我不确定在特定行之后和下方打印的 perl 语法。

while(<file1>)
{
    if () # if we read the phrase "My name" in file1 start printing after this     +line
    {
        print  #print the contents into file3(output file)
        if() # if we read the phrase "End" in file1 stop printing the content into     +file3
    }
}

我希望我的问题很清楚。任何帮助表示赞赏。

【问题讨论】:

  • (/^My name is/../^End/) !~ /^1?$|E/ and print while &lt;file1&gt;
  • @ysth 在您的模式中1 表示行号,那么您为什么使用^$
  • 有谁知道为什么 所有 答案——即使是被接受的答案——都被否决了?他们都在 cmets 中得到了积极的反馈。我知道每个人都可以根据自己的喜好投票,但这似乎不合理。

标签: regex perl


【解决方案1】:

好的。我相信您的问题是关于打印到输出文件的 perl 语法。我将尝试根据您正在尝试做的事情的描述为您提供更完整的解决方案。这只是一个快速非常简单的代码示例。 (对于一些参考,您可能还想查看http://perlmaven.com/slurp。)

首先让我们将您的新文件称为“newfile.txt”。 然后让我们称你为源文件“sourcefile.txt”。这里 是一些带有 cmets 的代码:

# First I would set the buffer to flush everything to to newfile.txt  
$++;

# Now open newfile.txt for writing the intformation you want
open my $NEWFILE, '>', 'newfile.txt';

# Now open sourcerfile.txt (or iterate over a list of them)
open my $SOURCEFILE, '<', 'sourcefile.txt';

# Now go through the sourcefile and get info you want to 
# add to your newfile

# set a variable to print data to newfile - initialize to
# N or false
$data_wanted = "N";

# open sourcefile and start reading lines

while <$SOURCEFILE> {
      # Test to see if data is between My Name and 
      if ($_ =~ /^My name/ ) {
          $data_wanted = "N";
      } 
      elsif ($_ =~ /^End/ ) {
          $data_wanted = "N";
          next;
      } 
      elsif ($_ =~ /^STUFF TO OMIT/) {
          $data_wanted = "N";
      }
      else {
          $data_wanted = "Y";
      }

      if ( $data_wanted eq "Y" ) {
          print $NEWFILE $_;
      }

      # you don't really need this but
      # it will show you how this works in perl
      next;  

}  # end of while

# finish by closing the files

close $SOURCEFILE;
close $NEWFILE;

##########################################

希望这会有所帮助;-)

【讨论】:

  • 感谢您的逻辑。它在一定程度上帮助了我。只是为了增加您的逻辑,您能否在您的 while 循环中编写另一个案例以省略 sourcefile.txt 中包含“我的名字”的行之前的代码行
  • 另外,如果“我的名字...”和“结束...”之间有我们想要过滤的行。我们如何在将内容从 SOURCEFILE 复制到 NEWFILE 时省略它们。提前感谢您的帮助。
  • 对于额外的行过滤,您可以在下面对我的回答添加“elsif”语句。希望对您有所帮助。
  • 我现在很忙。我将在大约 8 小时后对代码进行修改。
  • 好的,当然。谢谢您的帮助。此外,当您编辑它时,请考虑如果我们在“End XYZ”之后的文本文件中有语句并且我们只想复制内容直到“End XYZ”行之前的情况。我尝试使用“last”关键字来打破循环,但它不起作用。
【解决方案2】:

您可以使用几个正则表达式之一获得My name is &lt;name&gt;.End &lt;name&gt; 之间的行。

懒惰:

My name is ([^\n]+)\.(.*?)End \1

贪婪:

My name is ([^\n]+)\.(.*)End \1

优化:

My name is ([^\s]+)\.((?:[^\n]*(?!End \1)\n)+)End \1

无论哪种方式,您都需要s 修饰符。如果文件中需要解析多个内容,则需要 g 修饰符。

反向引用确保匹配而不需要知道名称。这意味着您想要的内容将在捕获组 2 中。

这三个正则表达式有什么区别?速度!根据需要解析的文件数量,您可能需要速度。

如果您正在解析的内容存在显着差异,则优化后的效果最好。它的工作方式与this other regex I wrote 相同。 (如果速度很重要,你应该做一些测试。)

从这里编写代码应该相当简单。

【讨论】:

  • 感谢您的帮助。我认为在您的模式中 1 表示行号。如果我们在 "My name ..." 之前有行,而我们不知道 "My name.." 的行号怎么办。在这种情况下,正则表达式有何不同。此外,如果“我的名字...”和“结束...”之间有行,我们想通过根据我们的要求过滤它们来省略它们,那么在这种情况下如何实现正则表达式。我认为这很复杂。感谢您的帮助。
  • @V.Tej 我已经测试了这些并且它们可以工作,即使您的文件在My name 之前有行。 \1 不是指行号;正如我所说,这是一个反向引用。修改正则表达式以过滤掉行会很容易。
【解决方案3】:

这是你要找的吗?

while (<>) {
    if ( /^My name / .. /^End / ) {
        if ( /^My name / ) {
            # Do nothing, or anything you would like for this line.
        } elsif ( /^End / ) {
            # Do nothing, or anything you would like for this line.
        } else {
           print $_;
        }
    }
}

【讨论】:

  • 是的,逻辑看起来和你写的代码很像。代码第二行中的 .. 表示什么。这是否意味着“我的名字”和“结束”之间的任何一条线。
  • 是的,“..”表示匹配“我的名字”和“结束”之间的所有行。
  • 对于额外的行过滤(如上面评论中的要求),您可以在内部 if 条件中附加“elsif”语句。如果您需要进一步的帮助,请告诉我。
  • 感谢您的帮助。上面编辑的代码已经很清晰了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-21
  • 1970-01-01
  • 2021-01-20
  • 2023-03-08
相关资源
最近更新 更多