BASH:如何对管道中的数字执行算术运算

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3272215/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 22:20:25  来源:igfitidea点击:

BASH: how to perform arithmetic on numbers in a pipe

linuxbashunixshellmath

提问by brice

I am getting a stream of numbers in a pipe, and would like to perform some operations before passing them on to the next section, but I'm a little lost about how I would go about it without breaking the pipe.

我在管道中获得了一个数字流,并且想在将它们传递到下一部分之前执行一些操作,但是我对如何在不破坏管道的情况下进行操作有点迷茫。

for example

例如

> echo "1 2 3 4 5" | some command | cat 
1 4 9 16 25
>

Would you have any ideas on how to make something like this work? The actual operation I want to perform is simply adding one to every number.

你对如何制作这样的作品有什么想法吗?我想要执行的实际操作只是将每个数字加一。

采纳答案by Matthew Flaschen

echo 1 2 3 4 5|{
  read line; 
  for i in $line;
  do
    echo -n "$((i * i)) "; 
  done; 
  echo
}

The {} creates a grouping. You could instead create a script for that.

{} 创建一个分组。您可以为此创建一个脚本。

回答by tokland

I'd write:

我会写:

echo "1 2 3 4 5" | {
  for N in $(cat); do
    echo $((N ** 2))
  done | xargs
}

We can think of it as a "map" (functional programming). There are a lot of ways of writing a "map" function in bash (using stdin, function args, ...), for example:

我们可以将其视为“地图”(函数式编程)。有很多方法可以在 bash 中编写“map”函数(使用 stdin、函数参数等),例如:

map_stdin() {
  local FUNCTION=
  while read LINE; do
    $FUNCTION $LINE
  done
}

square() { echo "$(( * ))"; }

$ echo "1 2 3 4 5" | xargs -n1 | map_stdin square | xargs
1 4 9 16 25

回答by aoakenfo

echo 1 2 3 4 5 | xargs -n 1 expr -1 +

回答by lasseoe

Or..

或者..

echo "1 2 3 4 5" | xargs -n 1 | while read number 
 do
   echo $((number * number))
 done

回答by tilo

echo 1 2 3 4 5 | xargs -n 1 bash -c 'echo $((*))' args 

回答by Niko

Using awk is another solution, which also works with floats

使用 awk 是另一种解决方案,它也适用于浮点数

echo "1 2 3 4 5" | xargs -n1 | awk '{print ^2}' | xargs

or use a loop

或使用循环

for x in 1 2 3 4 5; do echo $((x**2)); done | xargs
for x in $(echo "1 2 3 4 5"); do echo $x^2 | bc; done | xargs # alternative solution
for x in $(seq 5); do python -c "print($x**2)"; done | xargs  # alternative solution but slower than the above
# or make it neat by defining a function to do basic math in bash, e.g.:
calc() { awk "BEGIN{print $*}"; } 
for x in $(seq 5); do calc $x^2; done | xargs

回答by SiggyF

Or you can pipe to expression to bc:

或者您可以通过管道将表达式传递给 bc:

echo "1 2 3 4 5" | (
  read line; 
  for i in $line;
  do
    echo $i^2 | bc; 
  done; 
  echo
)

回答by Amber

If you prefer Python:

如果你更喜欢 Python:

#!/bin/python
num = input()
while num:
    print(int(num) + 1) # Whatever manipulation you want
    try:
        num = input()
    except EOFError:
        break

回答by Bluu

xargs, xargs, xargs

xargs, xargs, xargs

echo 1 2 3 4 5 | xargs -n1 echo | xargs -I NUMBER expr NUMBER \* NUMBER | xargs

Or, go parallel:

或者,并行:

squareit () { expr  \* ; }
export -f squareit
echo 1 2 3 4 5 | xargs -n1 | parallel --gnu squareit | xargs

Which would be way simpler if you passed your pipe as a standard set of args:

如果您将管道作为标准参数集传递,这会更简单:

parallel --gnu "expr {} \* {}" ::: $(echo 1 2 3 4 5) | xargs

Or even:

甚至:

parallel --gnu "expr {} \* {}" ::: 1 2 3 4 5 | xargs

Really worth taking a look at the examples in the doc: https://www.gnu.org/software/parallel/man.html

确实值得一看文档中的示例:https: //www.gnu.org/software/parallel/man.html

回答by Aleks-Daniel Jakimenko-A.

Yoi might like something like this:

Yoi 可能喜欢这样的东西:

echo "1 2 3 4 5" | perl -ne 'print $_ ** 2, " " for split / /, $_'

or even like this:

甚至像这样:

echo "1 2 3 4 5" | perl -ne 'print join " ", map {$_ ** 2} split / /, $_'