【问题标题】:awk search fields from one file within other from inside a Perl scriptawk 从 Perl 脚本中的一个文件中的另一个文件中搜索字段
【发布时间】:2018-05-31 03:13:23
【问题描述】:

我正在比较以下两个文件的重复项

文件1

ac-list hostname permit tcp host 110.185.35.111 host 10.185.38.220 eq 1222

文件2

ac-list hostname permit tcp host 10.185.35.111 host 10.185.38.220 eq 1222

我的脚本如下

#!/usr/bin/perl

open( SOURCE,      "</home/amp/surevy01/file1" );
open( DESTINATION, "</home/amp/surevy01/file2" );

while ( my $line = <SOURCE> ) {

    while ( my $line1 = <DESTINATION> ) {

        chomp( $line );
        chomp( $line1 );

        my @columns = split( ' ', $line );
        my @gitcols = split( ' ', $line1 );

        my $fld1    = $columns[4];
        my $fld2    = $columns[5];
        my $fld3    = $columns[6];
        my $fld4    = $columns[7];
        my $fld5    = $columns[9];

        my $gitfld1 = $gitcols[4];
        my $gitfld2 = $gitcols[5];
        my $gitfld3 = $gitcols[6];
        my $gitfld4 = $gitcols[7];
        my $gitfld5 = $gitcols[9];

        if ( $line == $line1
            || awk '/$fld1/ && /host/ && /$fld2/ && /$fld3/ && /$fld4/ && /$fld5/' $line1 ) {

            print "\n All duplicate";
        }
    }
}

我收到以下错误:

在 ./perltest 第 25 行,“awk '/$fld1/ && /host/ && /$fld2/ && /$fld3/ && /$fld4/ && /$fld5/'”附近的操作员预期的位置找到字符串(您需要预先声明 awk 吗?)
标量在 ./perltest 第 25 行,靠近“'/$fld1/ && /host/ && /$fld2/ && /$fld3/ && /$fld4/ && /$fld5/' $line1” (缺少运算符在 $line1 之前?)
./perltest 第 25 行的语法错误,靠近“awk '/$fld1/ && /host/ && /$fld2/ && /$fld3/ && /$fld4/ && /$fld5/'”
./perltest 第 30 行,“}”附近的语法错误
./perltest 的执行由于编译错误而中止。

但是,如果不使用 awk 命令,我的脚本运行良好。

【问题讨论】:

  • Perl 中没有“awk 命令”。你从哪里得到的?
  • awk '/$fld1/ &amp;&amp; /host/ &amp;&amp; /$fld2/ &amp;&amp; /$fld3/ &amp;&amp; /$fld4/ &amp;&amp; /$fld5/' $line1 可能是指grep { /$fld1/ &amp;&amp; /host/ &amp;&amp; /$fld2/ &amp;&amp; /$fld3/ &amp;&amp; /$fld4/ &amp;&amp; /$fld5/ } ( $line1 )(Perl 没有awk 命令,但it has a grep command)。

标签: perl


【解决方案1】:

虽然我不确定为什么这个“比较”对你有用,但下面的代码做了你的代码似乎试图做的事情:

#!/usr/bin/perl

use strict;
use warnings;

my $file1 = shift || '/home/amp/surevy01/file1';
my $file2 = shift || '/home/amp/surevy01/file2';

my @cols = (4, 5, 6, 7, 9);

open(my $fh1, "<$file1") or die "Cannot open source: $file1\n";
open(my $fh2, "<$file1") or die "Cannot open destination: $file2\n";

while( my $line1 = <$fh1> ) {
  chomp $line1;
  my @cols1 = split ' ', $line1;

  while( my $line2 = <$fh2> ) {
    chomp $line2;
    my @cols2 = split ' ', $line2;

    my $count = 0;
    foreach my $i ( @cols ) {
      if( $cols1[$i] eq $cols2[$i] ) {
        $count++;
      }
    }
    if( $count == scalar @cols ) {
      print "All duplicate\n";
    }
  }
  seek $fh2, 0, 0;
}

关于您的代码,请注意:

  1. 如 cmets 对您的问题所述,awk 不是 Perl 命令。它是一种不同的编程语言。这解释了您遇到的第一个错误。
  2. Perl 中的 string 比较是eq== 用于比较数字。所以你应该使用$line eq $line1
  3. 您可以通过使用system 在Perl 脚本中使用awk,然后使用$? 获取返回状态,但这会非常低效。

另外请注意,目前的代码会将第一个文件的每一行与第二个文件的所有行进行比较,不提供知道何时打印All duplicate 字符串的上下文。也许您的意思是并排比较两个文件。为此,您可能需要检查diff,它与可以选择正确列的内容相结合,例如cutawk 甚至perl,这样可以相对容易地进行并排比较。

如果您需要做其他事情,您可能需要编辑您的问题并说明您想要实现的具体目标,并提供更长的输入文件以说明预期的输出。

【讨论】:

  • split /\s+/ 几乎从来都不是您想要的。 split ' ' 是你应该使用的,如果你想把一个字符串变成一个空格分隔的单词列表。
  • @melpomene,我按照你的说法留下split。确实,输入可能包含 empty 列,而 split /\s+/ 不会正确处理这些列。为此split /\s/ 可能更好。但是如果我们不知道输入的文件格式就很难说。
  • @JavierElices perldoc -f split: 作为另一种特殊情况,当 PATTERN 被省略或由单个空格字符组成的字符串(例如作为 ' ' 或 "\x20" ,但不是例如 // )。在这种情况下,EXPR 中的任何前导空格在拆分发生之前都会被删除,而 PATTERN 则被视为 /\s+/ ;
  • @melpomene,我没有想到那个,但你是对的。 Perl 充满了技巧... :-) 感谢您提醒我(以及其他可能阅读此内容的人)。
  • 你必须用seek $fh2,0,0重置$fh2上的文件迭代,否则它只会迭代一次。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-23
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 2011-04-26
相关资源
最近更新 更多