这是在 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,84
,SHELL 平均实时:0,48
你的程序慢的原因不是因为打印。您的程序很慢,因为您为 $NUMBERS
的每个元素调用了 nawk
的新副本。这是非常浪费的,你应该从一开始就重新考虑你的程序设计。看来您主要是想查看一个列表中的哪些数字存在于第二个列表中。如果你想在 nawk 中这样做,你应该先读取整个第一个列表,然后将元素存储在关联数组中,然后再从第二个文件中读取每个数字。
您可能可以使用 join
或 grep
.
更干净地解决此问题
编辑:这是一个使用 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
中
我正在尝试进行一些测量,我想知道通过 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,84
,SHELL 平均实时:0,48
你的程序慢的原因不是因为打印。您的程序很慢,因为您为 $NUMBERS
的每个元素调用了 nawk
的新副本。这是非常浪费的,你应该从一开始就重新考虑你的程序设计。看来您主要是想查看一个列表中的哪些数字存在于第二个列表中。如果你想在 nawk 中这样做,你应该先读取整个第一个列表,然后将元素存储在关联数组中,然后再从第二个文件中读取每个数字。
您可能可以使用 join
或 grep
.
编辑:这是一个使用 grep
的有效解决方案。它至少比原来的 shellfun()
.
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
中