2012-04-26 57 views
1

任何人都知道更好的方法来做到这一点,它是更快?日期为什么这么慢?


#!/bin/bash 

declare -A clientarray 
file=$1 
timer=$2 
e=$(date --date "now +$timer second" +%s) 

while read line 
do 

    if [ -n "${clientarray[$line]}" ]; then 
      let "clientarray[$line]=clientarray[$line]+1" 
      echo "$line: ${clientarray[$line]}" 

    elif [ -z "${clientarray[$line]}" ]; then 
      clientarray[$line]=1 
      echo "$line: ${clientarray[$line]}" 

    fi 
    if [ $(date +%s) -gt $e ]; then 
        e=$(date --date "now +$timer second" +%s) 

    fi 
done < <(tail -F $file | gawk -F"]" '/]/ {print $1}') 

这里是行的一个示例::

someline] 
someline2] 
somethingidontwant 
someline3] 
somethingelseidontwant 
someline4] 

并调用脚本:

此当前推动每秒高线到该脚本时是慢
bash script.sh somelogfile.log 1 

如果我注释掉if逻辑最后它变得非常快,但速度下降2/3rds。与光伏测试它:

(这是与如果逻辑):

[email protected]:~/graphs$ tail -F somelogfile.log | pv -N RAW -lc >/dev/null | 
         > bash script.sh somelogfile.log 1 | pv -N SCP -lc >/dev/null 

    RAW: 2.18k 0:00:16 [ 493/s ] [     <=>        ] 
    SCP: 593 0:00:16 [ 150/s ] [    <=>         ] 

(这是不)

[email protected]:~/graphs$ tail -F somelogfile.log | pv -N RAW -lc >/dev/null | 
         > bash script.sh somelogfile.log 1 | pv -N SCP -lc >/dev/null 

    RAW: 7.69k 0:00:15 [512/s] [          <=>   ] 
    SCP: 7.6k 0:00:15 [503/s] [        <=>     ] 

让我知道如果我的思念在我的脚本或测试的东西侧面,特别是任何“DOH!”的。 我认为在这一点上,我会很喜欢=)

+0

您正在阅读'$ line',但未在显示的代码中使用它。这是否将代码剥离到最低限度的再现?同样,除非定期更新,否则您不会使用'$ e'做任何事情。在每次迭代中必须运行外部命令('date')的事实总是会使得进程比只有内部命令执行时慢。最终,你可能会更好地使用Python或Perl或类似的东西;它可以避免新的流程开销,同时更简单地进行日期计算。 – 2012-04-26 18:46:59

+0

修复了这个问题,对不起,我通常使用我来代替行,我只是放了行,因为这是读取时使用的常见示例,并且错过了更改脚本的主体。 – patch 2012-04-27 14:01:37

+0

练习编写代码是一个不错的主意,因此您不需要在公开发布代码之前对其进行修改。那么你不会遇到这样的问题。 – 2012-04-27 14:26:12

回答

2

作为一个猜测,我会说这可能是因为,去年if ... fi块增加了每次迭代两个非内置命令。循环中的所有其他内容都是bash buildins,执行速度更快。有了它,您可以在测试中拨打date,并在if的正文中拨打另一个。此外,date --date每次调用时都必须解析并评估"now +$timer second"表达式,但由于​​的一般性,这可能不是非常快速。如果我是你,我会尝试用脚本语言重新实现它,并使用更多的本地处理日期/时间:Perl,Ruby,Python,无论你喜欢什么。

也似乎有一个bug:

if [ `date +%s` > $e ] ... 

这是说:执行命令date +%s和插值输出(比如12345)到另一个命令[ 12345 > $e ](到目前为止好)。该命令说:使用两个参数(12345])运行[内建,并将其标准输出流重定向到一个名为值$e(uh-oh)的文件。您可能想在此处使用-gt而不是>

+0

或者使用'[[$(date +%s)> $ e]]'(其中双括号是重要的部分,尽管避免反引号并使用'$(...)'也是很好的建议,当在SO注释中编写shell脚本)。 – 2012-04-26 18:48:57

+0

...除了在这种情况下'''按字典顺序排序而不是数字排序。所以,如果在你运行这个程序的时候,从这个纪元获得一个数字以来的秒数(不可否认),那么你会被洗掉;-) – wdebeaum 2012-04-26 18:55:12

+0

可能使用'time',这是一个buildin,而不是'date' , 帮帮我?我真的不明白脚本的作用,但似乎做了某种时机。 :) – 2012-04-26 18:55:42

0

我不确定你在做什么$e,但是你可以使用shell内置的printf打印当前日期,你可以通过调用date来打印当前日期。子流程调用往往很昂贵。例如,如果您不在glibc2上,您可以执行以下操作:

printf '%(%+)T\n' -1 

准确获取date命令的输出。%+不支持在glibc2的,所以你可以构建的东西与其他参数相同,或者类似的东西:

printf '%(%c %Z)T\n' -1 

如果您需要捕获和处理日期不知何故,那么你可能还需要一个子shell调用使用$()但有一个不错的机会,它仍然比date更快。