【问题标题】:which is the fastest way to print in awk这是在 awk 中打印的最快方法
【发布时间】:2016-08-21 06:56:17
【问题描述】:

我正在尝试进行一些测量,我想知道通过nawk 打印东西的最快方法是什么。 目前我使用printf ARR[2] " ";,但打印时间似乎比平时要多。

信息:我打印了大约 500 个数字,并在 printf 中添加了空格,这样打印出来的内容就不会粘在一起了。我也在 ksh 上运行脚本,在 unix oracle solaris 中。

像这样,打印所有内容大约需要 14 秒,有没有更快的方法可以做到这一点?

提前致谢!

更新

我关心的函数是 awkfun,我在调用它时使用time 来进行时间测量。 将NUMBERS 视为一个包含 1000 个随机数的变量,将XNUMBERS 视为一个包含 1000 个随机数的变量,但在这种格式中,123|321,因此它采用随机数反转它并在中间。 我正在检查每个NUMBERS 是否存在于XNUMBERS 中,如果存在,我只打印出相反的数字。

numfun() {
    NUMBERS=`nawk ' BEGIN{ 
        srand();
        for (i=0; i<=999; i++) {
            printf("%s\n", 100 + int(rand() * (899)));
        }   
    }'`
}
numfun
sleep 1
xnumfun() {
    XNUMBERS=`nawk ' BEGIN{ 
        srand();
        for (i=0; i<=999; i++) {
            XNUMBERS[i]= 100 + int(rand() * (899));
        }
        for (i=0; i<=999; i++) {
            ver=XNUMBERS[i] "";
                    rev = "";
            for (q=length(ver); q!=0; q--) {
                rev = rev substr(ver, q, 1);
            }
            printf("%s\n", XNUMBERS[i] "|" rev );
        }
    }'`
}
xnumfun
awkfun() {
    for n in $NUMBERS
    do
        echo "${XNUMBERS}" | nawk -v VAR=$n '
        {
            split($1,ARR,"|")
            if (VAR == ARR[1]){
                printf ARR[2] " ";
                exit;
            }
        }' 
    done

}
shellfun() {
    for n in $NUMBERS
    do
        for x in $XNUMBERS
        do
            if test "$n" -eq "${x%%\|*}"
                then
                echo "${x##*\|}";
                break;
            fi
            continue;
        done
    done
}
sleep 1
time awkfun;
echo "\nAWK TIME\n\n-----------------------------";
time shellfun;
echo "\nSHELL TIME\n\n-----------------------------";
time numfun;
echo "\nNUMBERS TIME\n\n-----------------------------";
time xnumfun;
echo "\nXNUMBERS TIME\n\n-----------------------------\n\nTOTAL TIME\n";

结果

仅供参考,提炼脚本后的结果,AWK平均实时=0,84SHELL平均实时:0,48

【问题讨论】:

  • 请显示完整的工作脚本和示例输入。
  • @JohnZwinck 刷新并查看我创建的脚本,以便您更好地了解我在做什么,感谢您的回复:)
  • 您可以从接受的答案中得出结论,工具会有所帮助,但您的脚本技能也会有所帮助。请记住:始终尽量避免在长循环中调用外部程序。
  • 最后的时间结果是?
  • @WalterA 刚刚在帖子中添加了结果作为更新,请查看!!

标签: shell unix awk printf ksh


【解决方案1】:

您的程序运行缓慢的原因不是因为打印。您的程序很慢,因为您为$NUMBERS 的每个元素调用nawk 的新副本。这是非常浪费的,你应该从一开始就重新考虑你的程序设计。看来您主要是想查看一个列表中的哪些数字存在于第二个列表中。如果您想在 nawk 中执行此操作,则应先读取整个第一个列表,并将元素存储在关联数组中,然后再从第二个文件中读取每个数字。

您可以使用joingrep 更干净地解决这个问题。


编辑:这是使用grep 的有效解决方案。它比原来的 shellfun() 至少快 20 倍。

shellfun2() {
    echo $XNUMBERS | tr ' ' '\n' | cut -d '|' -f1 \
        | grep -f <(echo $NUMBERS | tr ' ' '\n') | rev
}

它的工作方式是在管道之前从$XNUMBERS 获取所有数字(因此12|21 34|43 变为12\n34),然后将这些数字通过管道传递给grep-f 参数是$NUMBERS .这意味着我们在$NUMBERS 中搜索$XNUMBERS 的所有左侧,在打印匹配项后,我们只需使用rev 来反转它们。我们根本不需要$XNUMBERS 的右侧(所以也许您甚至可以一开始就停止生成它们,从而节省更多时间)。


编辑:由于您现在告诉我们您在 Solaris 而不是 Linux 上运行,因此您没有 rev,因此您可以将上面的 rev 替换为:

sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//'

您可以将grep 替换为/usr/xpg4/bin/grep 以获得支持-f 的增强版本。

【讨论】:

  • @hedgehog:您能从一开始就描述一下您要解决的实际问题吗?与其深入研究为什么多次运行 awk 速度很慢,不如让我们谈谈这些数字在您的程序中的实际含义,以及您想要用简单的英语完成什么。
  • @hedgehog:你是说你在 Linux 上,但你的 grep 没有 -f 选项?究竟是哪个Linux?至于“rev”,你可以从你的系统包管理器中安装它(不确定包名是什么,但你可以搜索)。
  • @hedgehog:当您将问题标记为“Linux”时,您将获得 Linux 答案。我现在将删除标签。
  • @hedgehog:我在答案的底部添加了一个部分,用于将代码从 Linux 移植到 Solaris。我没有机器可以测试它,但我怀疑它应该可以工作。
  • Shellfun:当你想跳过 rev 时,使用 ` echo $XNUMBERS | tr ' ' '\n' | grep -f
【解决方案2】:

您正在为 $NUMBERS 中的每个数字启动 nawk,在时间方面非常昂贵。

您可以使用 grep 过滤 $NUMBERS 以仅处理您感兴趣的数字。即

grep -f FileWithListOfNumbers FileWithListOfXnumbers >matched_numbers

会给你一个 XNUMBERS 的列表(在匹配的数字中),它们也在 NUMBERS 中

【讨论】:

  • 我完全同意你的看法,如果我不必只使用 awk 来做到这一点:/
  • 哦,我看到你添加了更多代码。在您的 numfun 函数中,您有答案:而不是 printf 分配给数组 NUMBERS[i]=100 + int(rand() * (899)) 并在 awk 脚本正文中迭代该数组(您已经知道如何做)。所以awk的numfun函数位和awk的awkfun函数位可以成为一个单独的awk脚本。
  • 该数组不能被脚本中的其他函数使用,因为它在 nawk 内部,它是本地的。所以我无法通过其他功能访问它
猜你喜欢
  • 2012-03-27
  • 2021-11-08
  • 2013-03-15
  • 1970-01-01
  • 1970-01-01
  • 2021-05-04
  • 1970-01-01
  • 2012-12-08
  • 2011-10-09
相关资源
最近更新 更多