逐行读取文件并与shell数组元素进行比较:ksh

时间:2014-04-23 11:16:56

标签: arrays awk

我有一个ID数组,我想从日志文件中打印与数组中包含的任何值匹配的行。输入文件格式如下所示,必须匹配的数字以粗体显示。

  

2014-04-22 05:42:17 | SPPEventQueue_skl0.cpp(449)| 6 | CG | DEBUG |执行
  2014-04-22 05:42:17 | abc.cpp(253)| 6 | USR | INFO | IN {Event :: removeEvent
  2014-04-22 05:42:17 | cax.cpp(253)| 5 | USR | INFO | removeEvent number = 46574731
  2014-04-22 05:42:17 | zaw.cpp(253)| 7 | USR | INFO |未找到任何活动。
  2014-04-22 05:42:17 | asdf.cpp(253)| 3 | USR | INFO | OUT}活动
  2014-04-22 05:42:17 | abcd.cpp(367)| 8 | CG | DEBUG | op Event :: Queue :: publish,publish
  2014-04-22 05:42:17 | efgh.cpp(253)| 11 | USR | INFO | IN {Queue :: Event
  2014-04-22 05:42:17 | xyz.cpp(253)| 4 | USR | INFO |在eventEumber的removeEvent中46574731
  2014-04-22 05:42:17 | Event.cpp(503)| 6 | CG | DEBUG | op Queue :: Event :: removeEvent optimized,
  2014-04-22 05:42:17 | form.cpp(253)| 1 | USR | INFO | IN {Queue :: EventQueue
  2014-04-22 05:42:17 | service.cpp(1242)| 4 | P | DEBUG | commitObject:事务1285:5851已提交   2014-04-22 05:42:17 | form.cpp(253)| 6 | USR | INFO | removeEvent number = 46574731

以下代码有一个数组,用于比较每行中给定文件粗体值的每个元素。它读取文件的每一行,将上面粗体显示的值与数组的每个元素进行比较。如果找到匹配项,则该行存储在输出文件中。 它工作正常但需要很长时间才能读取超过10000行并与每个数组元素进行比较。

while read -r line; do 
    typeset CURTHREADID=echo "$line" | cut -d "|" -f 3
    for index in ${THREADIDARR[@]}; do
      if [ $CURTHREADID == $index ]; then
            echo "$line" >> $OUTPUTFILE
            break
      fi
    done
done < $INPUTFILE

我曾尝试使用AWK编写相同的代码,但它给了我一个错误,我不知道我在哪里失败。我需要帮助才能使用AWK编写相同内容,以便加快输出速度。这是我的尝试:

awk -v Thvar="$THREADIDARR" '
BEGIN{  command=cut -d "|" -f 3 }
{ CURTHREADID=getline | command
for(index in Thvar){
 if(CURTHREADID == Thvar[index]){print;break;}
}}' $INPUTFILE

2 个答案:

答案 0 :(得分:2)

你可以尝试:

awk -va="${THREADIDARR[*]}" '
 {BEGIN {FS="|"; n=split(a,b," "); for (i=1; i<=n; i++) c[b[i]]=1}
 $3 in c {print}' $INPUTFILE

答案 1 :(得分:2)

由于我对ksh不太熟悉,以下是我使用awk解决问题的方法:

awk -F'|' -v a="${THREADIDARR[*]}" '
BEGIN{
  split(a,b," ")
  for(i in b) c[b[i]] 
}
$3 in c' $INPUTFILE

这将创建一个数组c,其键是输入数组的值。如果输入文件的第三列列在这些键中,则打印该行(默认操作)。


修改:这可能会使ksh更快一些。我已删除了echocut部分:

#!/bin/ksh    

while read line; do
    IFS=\| read a b id c <<<$line
    for i in ${THREADIDARR[*]}; do
        if [ $i = $id ]; then
            echo "$line" >> $OUTPUTFILE
            break
        fi
    done
done < $INPUTFILE

修改:关于您的第二个问题,您可以将输入字段分隔符更改为:],这样就可以将其余代码更多或更少地保留相同的:

$INPUTFILE

20140320 00:08:23.846 INFO [WebContainer : 1] . anything line
20140320 00:08:23.846 INFO [WebContainer : 2] . anything line
20140320 00:08:23.846 INFO [WebContainer : 3] . anything line
20140320 00:08:23.846 INFO [WebContainer : 4] . anything line
20140320 00:08:23.846 INFO [WebContainer : 5] . anything line

代码:

THREADIDARR=(1 3)
awk -F": |]" -v a="${THREADIDARR[*]}" ' # two different field separators 
BEGIN{
  split(a,b," ")
  for(i in b) c[b[i]]
} 
$2 in c' $INPUTFILE # returns true (print) or false (don't print)

输出:

20140320 00:08:23.846 INFO [WebContainer : 1] . anything line
20140320 00:08:23.846 INFO [WebContainer : 3] . anything line