这是在 awk 中打印的最快方法

which is the fastest way to print in awk

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

信息:我打印了大约 500 个数字,并在 printf 中添加了 space,这样在打印输出时就不会把所有内容都粘在一起了。我也是 运行 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(,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

你的程序慢的原因不是因为打印。您的程序很慢,因为您为 $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\)/&/;//D;s/.//'

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

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

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

grep -f FileWithListOfNumbers FileWithListOfXnumbers >matched_numbers

将为您提供 XNUMBERS(在 matched_numbers 中)的列表,这些列表也在 NUMBERS