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

时间:2012-11-01 17:07:09

标签: linux bash math

我正在寻找一种简单的方法来划分数字(或提供其他数学函数)。让我们说我有以下命令:

find . -name '*.mp4' | wc -l

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

我见过的例子并未涉及重定向/进入。

4 个答案:

答案 0 :(得分:27)

使用bc

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

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

Awk也非常强大:

$ find . -name '*.mp4' | wc -l | awk '{print $1/3}'
2.33333

如果使用wc

,您甚至不需要awk
$ find . -name '*.mp4' | awk 'END {print NR/3}'
2.33333

答案 1 :(得分: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

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

或使用bash,仅产生整数:

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

使用 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

使用最近的64位bash,您甚至可以使用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 ,但计算伪浮动可以通过以下方式完成:

$res

没有分叉,globstar包含两位数的舍入浮动值。

Nota :使用**shell connector时关注符号链接

介绍 bc

如果您计划进行大量计算,需要高精度并使用@glennjackman's ideas,则可以使用 长时间运行的mkfifo /tmp/mybcfifo exec 5> >(exec bc -l >/tmp/mybcfifo) exec 6</tmp/mybcfifo rm /tmp/mybcfifo 子流程

echo >&5 '12/34'
read -u 6 result
echo $result
.35294117647058823529

然后现在:

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

此子流程保持开放且可用:

$PI

计算echo >&5 '4*a(1)' read -u 6 PI echo $PI 3.14159265358979323844

exec 6<&-
exec 5>&-

终止子流程:

{1..157} / 42

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

计算范围answer to the ultimate question of life, the universe, and everything(我会让你谷歌 printf -v form "%s" "%5.3f "{,}{,}{,,};form+="%5.3f\n"; ;)

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

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

通过常规方式

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>&- } 子流程

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

让我们看看没有的

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

哇!我的树莓派上的“强>十秒 !!

然后 with

shell connector

小于一秒 !!

希望结果是一样的,但执行时间却大不相同!

我的source shell_connector.sh newConnector /usr/bin/bc -l 0 0 myBc 1764/42 result echo $result 42.00000000000000000000

我发布了一个连接器功能:Connector-bash on GitHub.com

{{1}}

答案 2 :(得分:2)

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

如果您有多个输出需要通过xargs,最好使用。使用{}作为表达式术语的占位符。

答案 3 :(得分:1)

根据您的bash版本,您甚至不需要找到这个简单的任务:

shopt -s nullglob globstar
files=( **/*.mp4 )
dc -e "3 k ${#files[@]} 3 / p"

此方法将正确处理包含换行符的文件名的奇怪边缘。