使用管道划分bash的最佳方法?

Bri*_*ian 13 linux math bash

我只是在寻找一种简单的方法来划分数字(或提供其他数学函数).假设我有以下命令:

find . -name '*.mp4' | wc -l
Run Code Online (Sandbox Code Playgroud)

如何取wc -l的结果并除以3?

我见过的例子并不涉及重定向输出.

dog*_*ane 32

使用bc:

$ bc -l <<< "scale=2;$(find . -name '*.mp4' | wc -l)/3"
2.33
Run Code Online (Sandbox Code Playgroud)

相反,bash shell只执行整数运算.

Awk也非常强大:

$ find . -name '*.mp4' | wc -l | awk '{print $1/3}'
2.33333
Run Code Online (Sandbox Code Playgroud)

你甚至不需要wc使用awk:

$ find . -name '*.mp4' | awk 'END {print NR/3}'
2.33333
Run Code Online (Sandbox Code Playgroud)


F. *_*uri 10

编辑2018-02-22:添加 shell connector

有多种方式:

取决于所需的精度要完成的计算数量!见shell connector进一步!

bc(二进制计算器)

find . -type f -name '*.mp4' -printf \\n | wc -l | xargs printf "%d/3\n" | bc -l
6243.33333333333333333333
Run Code Online (Sandbox Code Playgroud)

要么

echo $(find . -name '*.mp4' -printf \\n | wc -l)/3|bc -l
6243.33333333333333333333
Run Code Online (Sandbox Code Playgroud)

或者使用bash,仅产生整数:

echo $(($(find . -name '*.mp4' -printf \\n| wc -l)/3))
6243
Run Code Online (Sandbox Code Playgroud)

使用 interger内置数学处理器

res=000$((($(find  . -type f -name '*.mp4' -printf "1+")0)*1000/3))
printf -v res "%.2f" ${res:0:${#res}-3}.${res:${#res}-3}
echo $res
6243.33
Run Code Online (Sandbox Code Playgroud)

纯粹的

使用最近的64位bash,您甚至可以使用@glennjackman的使用思想globstar,但计算伪浮动可以通过以下方式完成:

shopt -s globstar
files=(**/*.mp4)
shopt -u globstar
res=$[${#files[*]}000/3]
printf -v res "%.2f" ${res:0:${#res}-3}.${res:${#res}-3}
echo $res
6243.33
Run Code Online (Sandbox Code Playgroud)

没有fork并$res包含两位数的舍入浮点值.

Nota:使用和时关心符号链接!globstar**

介绍 shell connector

如果你计划进行大量的计算,需要高精度并使用,你可以使用长时间运行的bc子进程:

mkfifo /tmp/mybcfifo
exec 5> >(exec bc -l >/tmp/mybcfifo)
exec 6</tmp/mybcfifo
rm /tmp/mybcfifo
Run Code Online (Sandbox Code Playgroud)

那么现在:

echo >&5 '12/34'
read -u 6 result
echo $result
.35294117647058823529
Run Code Online (Sandbox Code Playgroud)

此子进程保持打开状态并可用:

ps --sid $(ps ho sid $$) fw
  PID TTY      STAT   TIME COMMAND
18027 pts/9    Ss     0:00 bash
18258 pts/9    S      0:00  \_ bc -l
18789 pts/9    R+     0:00  \_ ps --sid 18027 fw
Run Code Online (Sandbox Code Playgroud)

计算$PI:

echo >&5 '4*a(1)'
read -u 6 PI
echo $PI
3.14159265358979323844
Run Code Online (Sandbox Code Playgroud)

终止子流程:

exec 6<&-
exec 5>&-
Run Code Online (Sandbox Code Playgroud)

小演示,关于使用管道划分bash的最佳方法!

计算范围{1..157} / 42(我会让你google for answer to the ultimate question of life, the universe, and everything;)

...并按行打印13个结果以减少输出:

printf -v form "%s" "%5.3f "{,}{,}{,,};form+="%5.3f\n";
Run Code Online (Sandbox Code Playgroud)

按常规方式

testBc(){
    for ((i=1; i<157; i++)) ;do
        echo $(bc -l <<<"$i/42");
    done
}
Run Code Online (Sandbox Code Playgroud)

通过使用长时间运行的bc子流程:

testLongBc(){ 
    mkfifo /tmp/mybcfifo;
    exec 5> >(exec bc -l >/tmp/mybcfifo);
    exec 6< /tmp/mybcfifo;
    rm /tmp/mybcfifo;
    for ((i=1; i<157; i++)) ;do
        echo "$i/42" 1>&5;
        read -u 6 result;
        echo $result;
    done;
    exec 6>&-;
    exec 5>&-
}
Run Code Online (Sandbox Code Playgroud)

让我们看看没有:

time printf "$form" $(testBc)
0.024 0.048 0.071 0.095 0.119 0.143 0.167 0.190 0.214 0.238 0.262 0.286 0.310
0.333 0.357 0.381 0.405 0.429 0.452 0.476 0.500 0.524 0.548 0.571 0.595 0.619
0.643 0.667 0.690 0.714 0.738 0.762 0.786 0.810 0.833 0.857 0.881 0.905 0.929
0.952 0.976 1.000 1.024 1.048 1.071 1.095 1.119 1.143 1.167 1.190 1.214 1.238
1.262 1.286 1.310 1.333 1.357 1.381 1.405 1.429 1.452 1.476 1.500 1.524 1.548
1.571 1.595 1.619 1.643 1.667 1.690 1.714 1.738 1.762 1.786 1.810 1.833 1.857
1.881 1.905 1.929 1.952 1.976 2.000 2.024 2.048 2.071 2.095 2.119 2.143 2.167
2.190 2.214 2.238 2.262 2.286 2.310 2.333 2.357 2.381 2.405 2.429 2.452 2.476
2.500 2.524 2.548 2.571 2.595 2.619 2.643 2.667 2.690 2.714 2.738 2.762 2.786
2.810 2.833 2.857 2.881 2.905 2.929 2.952 2.976 3.000 3.024 3.048 3.071 3.095
3.119 3.143 3.167 3.190 3.214 3.238 3.262 3.286 3.310 3.333 3.357 3.381 3.405
3.429 3.452 3.476 3.500 3.524 3.548 3.571 3.595 3.619 3.643 3.667 3.690 3.714

real    0m10.113s
user    0m0.900s
sys     0m1.290s
Run Code Online (Sandbox Code Playgroud)

哇!我的覆盆子Ten十秒!

然后:

time printf "$form" $(testLongBc)
0.024 0.048 0.071 0.095 0.119 0.143 0.167 0.190 0.214 0.238 0.262 0.286 0.310
0.333 0.357 0.381 0.405 0.429 0.452 0.476 0.500 0.524 0.548 0.571 0.595 0.619
0.643 0.667 0.690 0.714 0.738 0.762 0.786 0.810 0.833 0.857 0.881 0.905 0.929
0.952 0.976 1.000 1.024 1.048 1.071 1.095 1.119 1.143 1.167 1.190 1.214 1.238
1.262 1.286 1.310 1.333 1.357 1.381 1.405 1.429 1.452 1.476 1.500 1.524 1.548
1.571 1.595 1.619 1.643 1.667 1.690 1.714 1.738 1.762 1.786 1.810 1.833 1.857
1.881 1.905 1.929 1.952 1.976 2.000 2.024 2.048 2.071 2.095 2.119 2.143 2.167
2.190 2.214 2.238 2.262 2.286 2.310 2.333 2.357 2.381 2.405 2.429 2.452 2.476
2.500 2.524 2.548 2.571 2.595 2.619 2.643 2.667 2.690 2.714 2.738 2.762 2.786
2.810 2.833 2.857 2.881 2.905 2.929 2.952 2.976 3.000 3.024 3.048 3.071 3.095
3.119 3.143 3.167 3.190 3.214 3.238 3.262 3.286 3.310 3.333 3.357 3.381 3.405
3.429 3.452 3.476 3.500 3.524 3.548 3.571 3.595 3.619 3.643 3.667 3.690 3.714

real    0m0.670s
user    0m0.190s
sys     0m0.070s
Run Code Online (Sandbox Code Playgroud)

不到一秒 !!

希望结果是一样的,但执行时间是非常不同的!

我的 shell connector

我发布了一个连接器函数:GitHub.com 上的Connector-bash我自己站点上的 shell_connector.sh.

source shell_connector.sh
newConnector /usr/bin/bc -l 0 0
myBc 1764/42 result
echo $result
42.00000000000000000000
Run Code Online (Sandbox Code Playgroud)


Sep*_*eph 6

find . -name '*.mp4' | wc -l | xargs -I{} expr {} / 2

如果您想通过管道传输多个输出,则最好使用xargs。用作{}表达式术语的占位符。