通过 AWK 在文本文件中搜索数组的有效方法

通过 AWK 在文本文件中搜索数组的有效方法

我有一个包含大约 10k 号码的数组 SPLNO。现在我想从数组中的 MDN.TXT 文件(包含大约 1.5 条 lac 记录)中搜索订户号码。如果在数组中找到订户号码,它将执行以下操作。我的问题是它需要更多时间,因为对于一个数字,它要搜索 10k 条记录的整个数组。因此,对于 1.5 lac 记录,它会循环 (1.5lac*10K)。请建议有效的方法。

示例 SPLNO.TXT:

918542054921|30|1|2
918542144944|12|1|2
918542155955|12|1|2 918542166966|12
|1|2
918542255955|12|1|2
918542355955|12|1| 2 91
8542455955|12|1|2
918542555955 |12|1|2
918542955955|12|1|2

示例 MDN.TXT:

8542166966
8542355955
8542555955

awk -F"|"  'FNR==1 { ++counter}
counter==1 {SPLNOPULSE[$1]=$4;SPLNOAMT[$1]=$3;SPLNOMAXLEN[$1]=$2;next}
{
for ( mdn in SPLNOMAXLEN)
        {
         if ( ($1 ~ "^"mdn && length($1) <=SPLNOMAXLEN[mdn]) || ("91"$1 ~ "^"mdn && length("91"$1) <=SPLNOMAXLEN[mdn]) )
              {                              
                print found
               }
         else
                print not found
        }                             
 } ' SPLNO.TXT MDN.TXT

答案1

这是一种方法,使用perl.

#!/usr/bin/perl
# read the subscribers
open(A,"<","SPLNO.TXT");
while(<A>) {
 chomp;
 @a=split(/\|/,$_);
 $splnopulse{$a[0]}=$3;
 $splnoamt{$a[0]}=$2;
 $splnomaxlen{$a[0]}=$1;
}
close A;

# read the mdn, looking for matches
open(B,"<","MDN.TXT");
while(<B>) {
 chomp;
 @b=split(/\|/,$_);
 foreach $mdn (keys %splnomaxlen) {
  if($mdn eq $b[0] || "$mdn" eq "91" . $b[0]) {
   print "found\n";
  } else {
   print "not found\n";
  }
 }
}
close B;

答案2

在整个文件 2 中搜索文件 1 中的每一行的算法的时间性能为m * n.其中m是文件 2 行数,n是文件 1 行数。这变得非常慢而不是很快。
解决方案是首先对每个文件进行排序(即 *log(n) 时间),然后比较两个文件之间的行,如下所示:

  1. 使 i=1(文件 1 行号)和 j=1(文件 2 行号)。
  2. a=(file 1)[line i]与之比较b=(file 2)[line j]
  3. if a<b;然后增加 i,返回到 2(检查文件 1 的结尾)。
  4. if a>b;然后增加 j,返回到 2(检查文件 2 的末尾)。
  5. if a=b;这是一个匹配,打印它,增加 i。

其执行时间仅为:(n + m读取所有行的时间)。

那么,整个过程的执行时间为:n*log(n) + m*log(m) + n + m
其中 O(n) 为:n * log(n)for n > m.

排序很容易,只需sort对每个文件使用命令:

sort -t '|' -k 1 file01.csv > file01-sorted.csv

然后在 awk 中执行上述过程。

编辑:我突然想到,如果 SPLNO 的所有 10k 个数字都是唯一的(没有重复)。并且MDN.TXT也有独特的记录。然后,连接两个文件并搜索重复值也将为您提供解决方案。这适用于简单的平等。在大多数情况下,正则表达式匹配会打破这个想法。

相关内容