使用管道在bash中分裂的最佳方法



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

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

如何将WC -L的结果除以3?

我见过的示例不处理重新定向/in。

使用 bc

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

相反,bash壳仅执行整数算术。

尴尬也非常强大:

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

如果使用awk

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

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

有多种方式:

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

使用bc(二进制计算器)

find . -type f -name '*.mp4' -printf \n | wc -l | xargs printf "%d/3n" | 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

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

纯bash

有了最近的64bits 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

没有叉子,$res包含两个数字圆形的浮动值。

nota :使用globstar**

引入 shell connector

如果您打算进行大量钙调,需要高精度并使用bash,则可以使用长期运行bc sub Process

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(我会让您Google for answer to the ultimate question of life, the universe, and everything ;)

...并打印13线结果,以减少输出:

printf -v form "%s" "%5.3f "{,}{,}{,,};form+="%5.3fn";

按常规方式

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

使用长期运行bc sub Process

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

哇!十秒钟在我的Raspberry-pi上!

然后

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上的连接器式键 和我自己网站上的shell_connector.sh。

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

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

如果您想通过xargs进行多个输出,则最好使用。使用{}作为表达式的占位符。

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

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

此方法将正确处理包含新线的文件名的奇异EDGECase。

相关内容

  • 没有找到相关文章

最新更新