简体   繁体   English

如果找到搜索模式,则 Append 文本位于行尾

[英]Append text in the end of line if search pattern is found

This is my first question on this forum:).这是我在这个论坛上的第一个问题:)。

I have a file something like:我有一个类似的文件:

----File--------
XI39/XM79 XI39/XM79#G XI39/XM79#S XI39/XM79#D XI39/XM79#B XI39/XM79#DN append_text! 
+ search_pattern
+ w=5e-07 l=3.85e-07 sa=4.1e-07 sb=4.1e-07 ad=2.05e-13 as=2.05e-13 pd=1.82e-06

XI57/XM0@1 XI57/XM0@1#G XI57/XM0@1#S XI57/XM0@1#D XI57/XM0@1#B XI57/XM0@1#DN
+ search_pattern
+ w=1e-06 l=3.85e-07 sa=4.1e-07 sb=1.215e-06 ad=2.1e-13 as=4.1e-13 pd=1.42e-06

I want to search for "search_pattern" and if found look at one line above and append "append_text."我想搜索“search_pattern”,如果找到,请查看上面的一行和 append“append_text”。 in end of line if its not present.如果它不存在,则在行尾。

So the output file should be:-所以 output 文件应该是:-

------------output file------ - - - - - - 输出文件 - - -

XI39/XM79 XI39/XM79#G XI39/XM79#S XI39/XM79#D XI39/XM79#B XI39/XM79#DN append_text! 
+ search_pattern
+ w=5e-07 l=3.85e-07 sa=4.1e-07 sb=4.1e-07 ad=2.05e-13 as=2.05e-13 pd=1.82e-06

XI57/XM0@1 XI57/XM0@1#G XI57/XM0@1#S XI57/XM0@1#D XI57/XM0@1#B XI57/XM0@1#DN append_text!
+ search_pattern
+ w=1e-06 l=3.85e-07 sa=4.1e-07 sb=1.215e-06 ad=2.1e-13 as=4.1e-13 pd=1.42e-06

I know perl a little so can do file operations but not good at all with pattern matching.我知道 perl 有点,所以可以进行文件操作,但在模式匹配方面一点也不好。 Any pointer will be helpful.任何指针都会有所帮助。

We can append the text in more ways.. Lets try this one我们可以通过更多方式 append 文本..让我们试试这个

Push all your data into array将所有数据推入数组

push(@allline, <DATA>);  

Iterate for loop迭代for循环

for(my $i=0; $i < $#allline; $i++)
{

Catch up the Matched line and previous line赶上Matched lineprevious line

    my $j = $i; $j--;

If matches found then go back to the previous line如果找到匹配项,则 go 返回上一行

    if($allline[$i]=~m/\+\s*search_pattern/)
    {

Check the append_text availability检查append_text可用性

        if($allline[$j]!~m/append_text/)
        {
            $allline[$j]=~s/$/ \*\*append_text\*\*/;
        }
        elsif($allline[$j]=~m/append_text/)
        {
            $allline[$j]=~s/append_text/\*\*append_text\*\*/;
        }
    }
}

Check your output检查您的 output

print join "", @allline;


__DATA__
XI39/XM79 XI39/XM79#G XI39/XM79#S XI39/XM79#D XI39/XM79#B XI39/XM79#DN append_text! 
+ search_pattern
+ w=5e-07 l=3.85e-07 sa=4.1e-07 sb=4.1e-07 ad=2.05e-13 as=2.05e-13 pd=1.82e-06

XI57/XM0@1 XI57/XM0@1#G XI57/XM0@1#S XI57/XM0@1#D XI57/XM0@1#B XI57/XM0@1#DN
+ search_pattern
+ w=1e-06 l=3.85e-07 sa=4.1e-07 sb=1.215e-06 ad=2.1e-13 as=4.1e-13 pd=1.42e-06

Output Output

 XI39/XM79 XI39/XM79#G XI39/XM79#S XI39/XM79#D XI39/XM79#B XI39/XM79#DN \*\*append_text\*\*!
 + search_pattern
 + w=5e-07 l=3.85e-07 sa=4.1e-07 sb=4.1e-07 ad=2.05e-13 as=2.05e-13 pd=1.82e-06

 XI57/XM0@1 XI57/XM0@1#G XI57/XM0@1#S XI57/XM0@1#D XI57/XM0@1#B XI57/XM0@1#DN \*\*append_text\*\*
 + search_pattern
 + w=1e-06 l=3.85e-07 sa=4.1e-07 sb=1.215e-06 ad=2.1e-13 as=4.1e-13 pd=1.42e-06

You can do this with a line buffer.您可以使用行缓冲区来执行此操作。 You read lines from the file and save the previous one you've read.您从文件中读取行并保存您已阅读的前一行。 When you find a line that matches your criteria, you modify the previous line and output it.当您找到符合您的条件的行时,您修改前一行并 output 它。 The current line becomes the previous line and you keep going:当前行变为上一行,然后继续:

use v5.12;
use warnings;

chomp( my $previous_line = <> );
while( <> ) {
    chomp;
    if( /search_pattern/ and $previous_line !~ / append_text!\z/ ) {
        $previous_line .= " append_text!";
        }

    say $previous_line;
    $previous_line = $_;
    }

say $previous_line;

This is something that someone on the second day of my Learning Perl could do and understand.这是我学习 Perl的第二天有人可以做和理解的事情。 There are no fancy regex features.没有花哨的正则表达式功能。

The same thing works if the previous interesting line is further away.如果前面有趣的线更远,同样的事情也有效。 You can keep a small line window array and once you find the line that triggers an action, do whatever you want to the previous lines:您可以保留一个小行 window 数组,一旦找到触发动作的行,对前面的行执行任何操作:

use v5.12;
use warnings;

my $buffer_size = 3;
my @line_window = map { scalar <> } 1 .. $buffer_size;
chomp( @line_window );

while( <> ) {
    chomp;
    if( /search_pattern/ and $line_window[0] !~ / append_text!\z/ ) {
        $line_window[0] .= " append_text!";
        }

    say shift @line_window;
    push @line_window, $_;
    }

say join "\n", @line_window;

Thanks Everyone for sharing there thought.感谢大家分享那里的想法。 it was really insightful and encourage me more to learn.这真的很有见地,并鼓励我更多地学习。

Based on various reply this is something I wrote and went with:-根据各种回复,这是我写的并随身携带的东西:-

#!/usr/bin/perl

use strict;
use warnings;

open(FH, "</home/sksingh/file");
my $this_line = "";
my $line_to_print = "";
while(<FH>) {
    my $last_line = $this_line;
    $this_line = $_;
    $line_to_print = $last_line;
    if ($this_line =~ /search_pattern/) {
        if($last_line =~ /append_txt!/) {
          $line_to_print = $last_line;
        }
        else {
          chomp($last_line);
          $line_to_print = "$last_line" . "psub!\n";
        }
      }
    print $line_to_print;
}
close (FH);

Again thanks for reply.再次感谢您的回复。

Currently the input file is of around 100 mb.目前输入文件约为 100 mb。 It in coming days i might have to precess file up till 3 GB.在接下来的几天里,我可能不得不将文件处理到 3 GB。 Not sure how this code will scale but for now I am good to go.不确定这段代码将如何扩展,但现在我对 go 很满意。

---Sandeep--- ---桑迪普---

Desired result can be achieved with perl one liner使用 perl 一个衬垫可以达到预期的效果

perl -007 -pe "s/(#DN)(\s+\+ search_pattern)/$1 append_text!$2/gs" filename

Or you could use following perl code (NOTE: it uses DATA block for test purpose)或者您可以使用以下 perl 代码(注意:它使用 DATA 块进行测试)

use strict;
use warnings;
use feature 'say';

my $data = do { local $/; <DATA> };

$data =~ s/(#DN)(\s+\+ search_pattern)/$1 append_text!$2/gs;

say $data;

__DATA__
----File--------
XI39/XM79 XI39/XM79#G XI39/XM79#S XI39/XM79#D XI39/XM79#B XI39/XM79#DN append_text! 
+ search_pattern
+ w=5e-07 l=3.85e-07 sa=4.1e-07 sb=4.1e-07 ad=2.05e-13 as=2.05e-13 pd=1.82e-06

XI57/XM0@1 XI57/XM0@1#G XI57/XM0@1#S XI57/XM0@1#D XI57/XM0@1#B XI57/XM0@1#DN
 + search_pattern
 + w=1e-06 l=3.85e-07 sa=4.1e-07 sb=1.215e-06 ad=2.1e-13 as=4.1e-13 pd=1.42e-06

Or even better with look behind to not includes append_text!或者甚至更好地向后看,不包括append_text append_text! in regular expression (for case if the line before + search_pattern has irregular pattern)在正则表达式中(如果+ search_pattern之前的行具有不规则模式)

use strict;
use warnings;
use feature 'say';

my $data = do { local $/; <DATA> };

$data =~ s/(?<!append_text!)(\s+\+ search_pattern)/ append_text!$1/gs;

say $data;

__DATA__
----File--------
XI39/XM79 XI39/XM79#G XI39/XM79#S XI39/XM79#D XI39/XM79#B XI39/XM79#DN append_text! 
+ search_pattern
+ w=5e-07 l=3.85e-07 sa=4.1e-07 sb=4.1e-07 ad=2.05e-13 as=2.05e-13 pd=1.82e-06

XI57/XM0@1 XI57/XM0@1#G XI57/XM0@1#S XI57/XM0@1#D XI57/XM0@1#B XI57/XM0@1#DN
+ search_pattern
+ w=1e-06 l=3.85e-07 sa=4.1e-07 sb=1.215e-06 ad=2.1e-13 as=4.1e-13 pd=1.42e-06

Output Output

----File--------
XI39/XM79 XI39/XM79#G XI39/XM79#S XI39/XM79#D XI39/XM79#B XI39/XM79#DN append_text!
+ search_pattern
+ w=5e-07 l=3.85e-07 sa=4.1e-07 sb=4.1e-07 ad=2.05e-13 as=2.05e-13 pd=1.82e-06

XI57/XM0@1 XI57/XM0@1#G XI57/XM0@1#S XI57/XM0@1#D XI57/XM0@1#B XI57/XM0@1#DN append_text!
 + search_pattern
 + w=1e-06 l=3.85e-07 sa=4.1e-07 sb=1.215e-06 ad=2.1e-13 as=4.1e-13 pd=1.42e-06
while(<Your filehandle name>)
{
if ($string =~ m/search_pattern/g) 
{
$_=~ s/append_text/**append_text**/g;
}
close(filehandle name)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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