简体   繁体   English

如何使用Perl从文件中选择行

[英]How to select lines from a file using Perl

I am trying to check each line in a file for a string and print that line if it has that string. 我正在尝试检查文件中的每一行是否为字符串,并打印该行(如果具有该字符串)。

Example of the array: 数组的示例:

---
BIP1288I: Message flow 'flow1' on execution group 'EG1' is running.

Additional thread instances: '0'
Deployed: '11/12/13 1:54 AM' in Bar file '/MSD/deploy/ENV/EG1/flow1.bar'
Last edited: '5/24/13 4:38 PM'.
Long description: ''
User-defined property names:
Keywords:

---
BIP1288I: Message flow 'flow2' on execution group 'EG1' is running.

Additional thread instances: '0'
Deployed: '11/12/13 1:54 AM' in Bar file '/MSD/deploy/ENV/EG1/flow2.bar'
Last edited: '5/24/13 4:38 PM'.
Long description: ''
Keywords:

----
BIP1288I: Message flow 'flow3' on execution group 'EG1' is running.

Additional thread instances: '0'
Deployed: '11/12/13 1:54 AM' in Bar file '/MSD/deploy/ENV/EG1/flow3.bar'
Last edited: '5/24/13 4:38 PM'.
Long description: ''
User-defined property names:
  'DBSchema' = 'SIDBT01'
  'LogLevel' = 'ERROR'
Keywords:

I am checking each line of this file to check for BIP1288I and flow name 'flow1'. 我正在检查此文件的每一行以检查BIP1288I和流名称“ flow1”。 I want my output to contain just this 我希望我的输出只包含这个

Additional thread instances: '0'
Deployed: '11/12/13 1:54 AM' in Bar file '/MSD/deploy/ENV/EG1/flow1.bar'
Last edited: '5/24/13 4:38 PM'.

This is my Perl code 这是我的Perl代码

foreach $line (@flows) {
  next if /^(\s)*$/;
  if ($line =~ "BIP1288I" && $line =~ "flow1") {
    $msg = "Flow found\n$line\n";
print "$msg";
  }}

It is unclear to me if you actually need to use perl , but this is quite simple with awk : 我不清楚您是否真的需要使用perl ,但这对于awk来说非常简单:

awk '/BIP1288I/ && /flow1/ { split($0, a, "\n"); print a[4],a[5],a[6]}' \
    RS=--- OFS=\\n input-file

You can use a2p to generate the similar script in perl . 您可以使用a2pperl生成类似的脚本。 ( a2p is the awk to perl translator. perl was largely modelled on awk . Never forget your roots.) Or: a2p是awk到perl的转换器perl很大程度上是基于awk建模的。请不要忘记您的根源。)或者:

perl -wnE 'BEGIN{ $/="---"; $,="\n"}; 
    @a=split("\n"); say $a[3],$a[4],$a[5] if (m/BIP1288I/ && m/flow1/)' input-file

This is not a tight test, since it will act if the strings appear anywhere in the record, but it should be sufficient. 这不是一个严格的测试,因为如果字符串出现在记录中的任何位置,它将起作用,但是这足够了。 You might need to match BIP1288I.*flow1 or restrict the match to the first line, depending on your requirements. 您可能需要匹配BIP1288I.*flow1或将匹配限制为第一行,具体取决于您的要求。

It's pretty unclear to me what you mean, but maybe grep can help you: 我不清楚您的意思,但grep可以帮助您:

grep "pattern1" your_file | grep "pattern2"

will print lines containing BOTH pattern1 and pattern2 将打印同时包含pattern1和pattern2的行

egrep "pattern1|pattern2" your_file

will print lines containing either pattern. 将打印包含任一模式的行。

grep -v "pattern" your_file

will print lines not matching pattern. 将打印不匹配图案的行。

So maybe you can use somethinhg like: 因此,也许您可​​以使用诸如以下的代码:

egrep "^Additional|flow1|^Last" your_file

I assume that the array @flows contains all the lines of your posted data. 我假设数组@flows包含您发布的数据的所有行。

use warnings; #always use these modules!
use strict; #always use these modules!

my $flag=0; #a flag to track if we found BIP1288I & flow1 in order to print the lines that follow
for my $line (@flows) {
    if ($flag==1) {
        if ($line=~/^(?:Additional thread|Deployed)/) {
            print $line; #we print the line only if flag is 1 and the line start with the words "Additional thread" or "Deployed" or "Last edited"
        }
        elsif ($line=~/^Last edited/) {
            print $line; #we print the line only if flag is 1 and the line start with the words "Additional thread" or "Deployed" or "Last edited" 
            $flag=0; #we reset the flag
        }
    }
    if ($line=~/BIP1288I: Message flow 'flow1'/) { #this the flow we are interested in
        $flag=1; #set the flag to 1 so we can start printing the lines that will follow
    }
}

This will print: 这将打印:

Additional thread instances: '0'
Deployed: '11/12/13 1:54 AM' in Bar file '/MSD/deploy/ENV/EG1/flow1.bar'
Last edited: '5/24/13 4:38 PM'.

Perhaps the following will be helpful: 也许以下内容会有所帮助:

use strict;
use warnings;

local $/ = '---';

while (<>) {
    print "$1$2$3\n"
      if /BIP1288I:.+'flow1'.+\n(Addi[^\n]+\n)(Depl[^\n]+\n)(Last[^\n]+\n)/s;
}

Usage: perl script.pl inFile [>outFile] 用法: perl script.pl inFile [>outFile]

The last, optional parameter directs output to a file. 最后一个可选参数将输出定向到文件。

Output on your dataset: 在数据集上输出:

Additional thread instances: '0'
Deployed: '11/12/13 1:54 AM' in Bar file '/MSD/deploy/ENV/EG1/flow1.bar'
Last edited: '5/24/13 4:38 PM'

Assuming that "---" separates records, you can set Perl's record separator ( $/ ) to "---" so you file's read in chunks of those records. 假设“ ---”分隔记录,则可以将Perl的记录分隔符( $/ )设置为“ ---”,以便在这些记录中分批读取文件。 Then you can match for "BIP1288I" and flow name "flow1" and capture the other info you want. 然后,您可以匹配“ BIP1288I”和流名称“ flow1”,并捕获所需的其他信息。

Hope this helps! 希望这可以帮助!

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

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