抓取行中的内容,并修复输出格式

时间:2014-07-10 15:00:23

标签: linux bash shell

我试图在centos上使用一个简单的脚本从文件中的行中取出信息并输出到csv文件。目前我已经使用我的脚本来实现结果,但是随着它的进展花费了太多时间。在我的source_file中,我有1000万行,大约需要1.5小时 SOURCE_FILE:

Jun 0:0:1.83 Q: I: C 12.25.89.22#408: V xx: Q: aa.test.com IN(B)
Jun 0:0:1.83 Q: I: C 14.25.87.12#302: V dd: Q: bb.try.com IN(B)
Jun 0:0:1.83 Q: I: C 19.46.41.13#361: V bb: Q: cc.try.test.com IN(B)
Jun 0:0:1.98 Q: I: C 14.25.89.16#435: V ss: Q: dd.test.com IN(B)
Jun 0:0:1.98 Q: I: C 14.25.86.28#353: V gg: Q: cc.ee.try.test.com IN(B)
Jun 0:0:1.91 Q: I: C 14.25.89.23#423: V xx: Q: .test.com IN(B)
Jun 0:0:1.91 Q: I: C 13.21.85.12#356: V dd: Q: gg-1-2.try.com IN(B)
Jun 0:0:1.91 Q: I: C 19.46.40.32#451: V dd: Q: hh.try.com IN(B)
Jun 0:0:1.91 Q: I: C 24.78.62.18#139: V ss: Q: .try.com IN(B)

Data_File:

test.com/
try.com/
try.test.com/

结果:

12.25.89.22,xx,test.com
14.25.87.12,dd,try.com
19.46.41.13,bb,try.test.com
14.25.89.16,ss,test.com
14.25.86.28,gg,try.test.com
14.25.89.23,xx,test.com
13.21.85.12,dd,try.com
19.46.40.32,dd,try.com
24.78.62.18,ss,try.com

我试过拿出IP,两个字和域名。域应该与Data_File匹配。域中的额外字符串将被截断 这是我的代码:

#!/bin/bash

sed -n '2,$p' Source_File | awk -F '[ #:]' '{print $10 " " $14 " " $18 "/"}' >> Temp_File

awk 'FNR==NR {arr[$0];next} {for (i in arr) {c=match($3,i);n=c&&(!b[$3]||c<b[$3])?i:n;b[$3]=c}$3=n}1' Data_File Temp_File >> Result

sed -i 's/ /,/g;s/\///g' Result

exit

匹配部分可能需要花费太多时间,但作为linux中的新功能,只有有限的知识。 有些人才可以暗示一下吗?或者可能是其他简单的脚本实现它? (可以是任何命令)。

3 个答案:

答案 0 :(得分:2)

您的解决方案需要太多不同的进程,这些进程一次又一次地处理整个文件。只需一个awk命令即可:

script.awk

BEGIN {
    OFS=","
}
NR>1{
    # Remove #...: from the IP
    match($6, /^(.*)#/,m)
    $6=m[1]

    # Get the two letter value
    gsub(":", "", $8)

    # Remove the optional leading dot from domain
    match($10,/\.?(.*)/,m)
    $10=m[1]

    print $6,$8,$10
}

执行:

awk -f script.awk input.file

我用1.2 GB的大文件测试了它,包含了1800万行,并且它使用了我4岁的桌面:4分33秒:

$ du -h input.file
1,2G    input.file

$ wc -l input.file
18874368  input.file

$ time awk -f script.awk input.file > output.file

real    4m33.991s
user    4m32.673s
sys 0m1.328s

答案 1 :(得分:2)

使用Perl

#! /bin/bash

input=/tmp/file
data=/tmp/data

export regex=$(perl -pe 'chomp; s/\///g; s/$/|/g' $data |\
       perl -pe 's/^/(/g; s/\|$/)/g')

perl -F':|\s|#' -alne '{ 
    $F[17] =~ s/.*?$ENV{"regex"}.*/$1/g; 
    print $F[9].",".$F[13].",".$F[17] }' $input 

输出:

bash test.sh 
12.25.89.22,xx,test.com
14.25.87.12,dd,try.com
19.46.41.13,bb,try.test.com
14.25.89.16,ss,test.com
14.25.86.28,gg,try.test.com
14.25.89.23,xx,test.com
13.21.85.12,dd,try.com
19.46.40.32,dd,try.com
24.78.62.18,ss,try.com

说明:

  1. 根据data文件
  2. 创建一个正则表达式
  3. 根据该正则表达式替换域
  4. 打印所选字段

答案 2 :(得分:1)

给出以下测试集:

$ cat dns.log 
Jun 0:0:1.83 Q: I: C 12.25.89.22#408: V xx: Q: aa.test.com IN(B)
Jun 0:0:1.83 Q: I: C 14.25.87.12#302: V dd: Q: bb.try.com IN(B)
Jun 0:0:1.83 Q: I: C 19.46.41.13#361: V bb: Q: cc.try.test.com IN(B)
Jun 0:0:1.98 Q: I: C 14.25.89.16#435: V ss: Q: dd.test.com IN(B)
Jun 0:0:1.98 Q: I: C 14.25.86.28#353: V gg: Q: cc.ee.try.test.com IN(B)
Jun 0:0:1.91 Q: I: C 14.25.89.23#423: V xx: Q: .test.com IN(B)
Jun 0:0:1.91 Q: I: C 13.21.85.12#356: V dd: Q: gg-1-2.try.com IN(B)
Jun 0:0:1.91 Q: I: C 19.46.40.32#451: V dd: Q: hh.try.com IN(B)
Jun 0:0:1.91 Q: I: C 24.78.62.18#139: V ss: Q: .try.com IN(B)

我使用单个Perl正则表达式替换获得似乎足够的东西:

sh$ perl -pe 's/.*C (.*)#.*V (..).*?([^.]*\.[^.]*) IN.*/\1,\2,\3/' < dns.log
12.25.89.22,xx,test.com
14.25.87.12,dd,try.com
19.46.41.13,bb,test.com
14.25.89.16,ss,test.com
14.25.86.28,gg,test.com
14.25.89.23,xx,test.com
13.21.85.12,dd,try.com
19.46.40.32,dd,try.com
24.78.62.18,ss,try.com