在 awk 的 BASH shell 中使用 bc 作为守护进程

Using bc as daemon in BASH shell from awk

# mkfifo inp out
# bc -ql  <inp  >out  &
[1] 6766
#
# exec 3>inp  4<out
# echo "scale=3; 4/5;" >&3
# read a <&4; echo $a
.800
#
# awk ' BEGIN { printf("4/5\n") >"/dev/fd/3"; exit 1;} '
# read a <&4; echo $a
.800
#
# awk ' BEGIN { printf("4/5\n") >"/dev/fd/3"; exit 1;} '
# awk ' BEGIN { getline a <"/dev/fd/4"; printf("%s\n", a); } '
^C

在BASH环境下我可以使用fifo与bc程序通信。 但是在 awk 中我可以写但不能用 getline 函数读取。 我如何从awk中的“/dev/fd/4”中读取。

我的 awk 版本是:mawk 1.3.3 1996 年 11 月,版权所有 (C) Michael D. Brennan

谢谢 拉齐

续:

我做了一些进一步的实验并总结了我的结果。 Awk 脚本语言最适合我的任务, 我需要使用 "bc" 因为我必须计算非常长的数字(大约 100 位数字)。 接下来的两个脚本显示使用命名管道比未命名管道快(大约 83 倍)。

1) 使用未命名的管道:

# time for((i=6000;i;i--)); do a=`echo "$i/1"|bc -ql`; done
real    0m13.936s

2) 使用命名管道:

# mkfifo in out
# bc -ql <in >out &
# exec 3>in 4<out
#
# time for((i=500000;i;i--)); do echo "$i/1" >&3; read a <&4; done
real    0m14.391s

3) 在 awk 环境中,bc 的使用比在 bash 中慢一点(大约 18 倍),但它是这样工作的:

# time awk ' BEGIN {
#               for(i=30000;i;i--){
#                   printf("%d/1\n",i) >"/dev/fd/3";
#                   system("read a </dev/fd/4; echo $a >tmp_1");
#                   getline a <"tmp_1"; close("tmp_1");}
#                  } '
real    0m14.178s

4) 当我尝试按照 "man awk" 做 accordig 时会出现什么问题? :

# awk ' BEGIN {
#         for(i=4;i;i--){
#         printf("%d/1\n",i) >"/dev/fd/3"; system("sleep .1");
#        "read a </dev/fd/4; echo $a" | getline a ;print a;}
#      } '
4.000
4.000
4.000
4.000

上面的 "awk" 脚本只能从管道中获取第一个数字。 其他三个数字留在管道中。 当我在上面的 awk 脚本之后读取管道时,这些将是可见的。

# for((;;)); do read a </dev/fd/4; echo $a; done
3.000
2.000
1.000

感谢您的关注。

尝试:

mkfifo inp out
bc -l  <inp  >out  &
awk ' BEGIN { printf("4/5\n"); exit 0;} ' > inp
read a < out; echo $a

awk ' BEGIN { printf("4/5\n"); exit 0;} ' > inp

awk ' BEGIN { getline a; printf("%s\n", a); exit 0 } ' < out

rm inp 
rm out

听起来你在寻找gawk的协同处理能力,见http://www.gnu.org/software/gawk/manual/gawk.html#Getline_002fCoprocess。不过,鉴于 awks 对数学函数的支持,我想知道您为什么要使用 bc...