【问题标题】:while loop extremely slow read filewhile循环读取文件速度极慢
【发布时间】:2014-04-18 12:13:15
【问题描述】:

我有一个 while 循环,它读取 ftp 日志文件并将其放入数组中,这样我就可以搜索数组并匹配/搜索流。不幸的是,while 循环要花很长时间才能通过文件,它是一个非常大的文件,但必须有另一种更快的方法来执行此操作。

# read file into array for original search results
while read FTP_SEARCH
do
ogl_date[count]=`echo $FTP_SEARCH | awk '{print $1, $2}'`
ogl_time[count]=`echo $FTP_SEARCH | awk '{print $3}'`
ogl_server[count]=`echo $FTP_SEARCH | awk '{print $4}'`
ogl_id[count]=`echo $FTP_SEARCH | awk '{print $5}'`
ogl_type[count]=`echo $FTP_SEARCH | awk -F '[' '{print $1}' | awk '{print $5}'`
ogl_pid[count]=`echo $FTP_SEARCH | awk -F'[' '{print $2}' | awk -F']' '{print $1}'`
ogl_commands[count]=`echo $FTP_SEARCH | awk '{
    for(i = 6; i <= NF; i++) 
        print $i;
    }'`

let "count += 1"

done < /tmp/ftp_search.14-12-02


Dec  1 23:59:03 sslmftp1 ftpd[4152]: USER xxxxxx  
Dec  1 23:59:03 sslmftp1 ftpd[4152]: PASS password  
Dec  1 23:59:03 sslmftp1 ftpd[4152]: FTP LOGIN FROM 172.19.x.xx [172.19.x.xx], xxxxxx  
Dec  1 23:59:03 sslmftp1 ftpd[4152]: PWD  
Dec  1 23:59:03 sslmftp1 ftpd[4152]: CWD /test/data/872507/  
Dec  1 23:59:03 sslmftp1 ftpd[4152]: TYPE Image`
Dec  1 23:59:03 sslmftp1 ftpd[4152]: PASV
Dec  1 23:59:04 sslmftp1 ftpd[4152]: NLST
Dec  1 23:59:04 sslmftp1 ftpd[4152]: FTP session closed
Dec  1 23:59:05 sslmftp1 ftpd[4683]: USER xxxxxx 
Dec  1 23:59:05 sslmftp1 ftpd[4683]: PASS password
Dec  1 23:59:05 sslmftp1 ftpd[4683]: FTP LOGIN FROM 172.19.1.24 [172.19.x.xx], xxxxxx 
Dec  1 23:59:05 sslmftp1 ftpd[4683]: PWD
Dec  1 23:59:05 sslmftp1 ftpd[4683]: CWD /test/data/944837/
Dec  1 23:59:05 sslmftp1 ftpd[4683]: TYPE Image

【问题讨论】:

  • 请张贴来自 ftp_search.14-12-02 的示例行。多次调用awk 来解析每一行是让你慢下来的原因。在bash 中有很多更好的解析方法,但我需要看看一行是什么样子才能建议最好的方法。
  • 或者,由于没有对其他外部程序的任何调用,它可以在 1 个 awk 程序中完成。需要样本数据。祝你好运。
  • Dec 1 23:59:03 sslmftp1 ftpd[4152]: USER xxxxxx Dec 1 23:59:03 sslmftp1 ftpd[4152]: PASS password Dec 1 23:59:03 sslmftp1 ftpd[4152]: FTP LOGIN FROM 172.19.x.xx [172.19.x.xx], xxxxxx Dec 1 23:59:03 sslmftp1 ftpd[4152]: PWD Dec 1 23:59:03 sslmftp1 ftpd[4152]: CWD /test/data/872507/ Dec 1 23:59:03 sslmftp1 ftpd[4152]: TYPE Image
  • 抱歉,我的评论中没有换行符,但它是 12 月初的新行
  • 您可以将输出添加到问题本身,而不是在评论中。

标签: bash while-loop


【解决方案1】:
  • 您无需保留迭代器即可添加到数组中。你可以简单地做array+=(item)不是array+=item)。
  • 获取输入中的列就像使用带有多个目标变量的read 一样简单。作为奖励,最后一个变量获取第 N 个单词和所有后续单词。见help [r]ead

这节省了大量的分叉,但我还没有测试它有多快。

ogl_date=()
[...]
ogl_commands=()

while read -r date1 date2 time server id type pid commands
do
    ogl_date+=("$date1 $date2")
    [...]
    ogl_commands+=("$commands")
done < /tmp/ftp_search.14-12-02

【讨论】:

  • 效果很好,但仍然很慢,需要几分钟才能完成所有工作,我可以尝试任何其他想法。非常感谢您的帮助!
  • 你想做什么?有没有办法在详细处理之前排除大部分文件?
  • @user2208986 您是按原样尝试的,还是在对其进行基准测试之前添加了所有自定义逻辑? shell 脚本中的主要性能杀手是分叉,这在使用`..`$(..)、调用外部命令和管道时发生。这个例子没有这些,但你的有很多。
  • 是的,它按原样工作。不确定如何使它更小,已经做了一个 grep 来最小化它。基本上,我有一个包含上述数据的 ftplpg 文件,我想通过搜索用户名或 IP 来显示整个流程。所以我想我会将数据读入数组,搜索条件,然后将该进程 id 与其他进程 id 匹配,这样我就可以得到整个流程。
  • bash 不适用于此类数据处理。使用通用编程语言执行此操作可能会快得多。
猜你喜欢
  • 1970-01-01
  • 2016-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-16
  • 2018-04-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多