在 bash 中使用管道进行划分的最佳方法?

问题描述 投票:0回答:4

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

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

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

我见过的例子不涉及重定向出/入。

linux bash math
4个回答
58
投票

使用

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

14
投票

编辑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
通过移位数字实现

伪浮点(乘以 100 并在距末尾 2 位数字处放置一个点):

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
纯粹

bash

您甚至可以使用

@glennjackman的想法使用globstar

,然后计算伪浮动可以通过以下方式完成:

shopt -s globstar shopt -s nullglob files=(**/*.mp4) shopt -u globstar res=000$(( ${#files[*]}000 / 3 )) printf -v res "%.2f" ${res:0:${#res}-3}.${res:${#res}-3} echo $res 6243.33
没有分叉,并且 

$res

 包含两位数四舍五入的浮动值。

注意:使用globstar**

时请注意
符号链接

介绍

shell connector

如果你打算做大量的计算,需要高精度并使用

bash长时间运行bc

子进程

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>&-
小演示,关于 

在 bash 中使用管道进行划分的最佳方法!

计算范围

{1..157} / 42

(我会让你谷歌搜索
answer to the ultimate question of life, the universe, and everything
;)

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

printf -v form "%s" "%5.3f "{,}{,}{,,};form+="%5.3f\n";
按常规方式

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
不到

一秒!!

希望结果是相同的,但执行时间却截然不同!

我的

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
    

6
投票

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



如果您想通过管道传输多个输出,则最好使用

xargs

。使用
{}
作为表达式术语的占位符。


1
投票
根据您的 bash 版本,您甚至不需要 find 来完成这个简单的任务:

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

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

© www.soinside.com 2019 - 2024. All rights reserved.