我试图在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中的新功能,只有有限的知识。 有些人才可以暗示一下吗?或者可能是其他简单的脚本实现它? (可以是任何命令)。
答案 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
说明:
data
文件
答案 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