代码之家  ›  专栏  ›  技术社区  ›  brice

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

  •  7
  • brice  · 技术社区  · 15 年前

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

    例如

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

    你对如何使这样的工作有什么想法吗?我要执行的实际操作只是在每个数字上添加一个。

    10 回复  |  直到 8 年前
        1
  •  7
  •   Matthew Flaschen    12 年前
    echo 1 2 3 4 5|{
      read line; 
      for i in $line;
      do
        echo -n "$((i * i)) "; 
      done; 
      echo
    }
    

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

        2
  •  4
  •   tokland    12 年前

    我会写:

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

    我们可以把它看作一个“地图”(函数式编程)。在bash中编写“map”函数有很多方法(使用stdin、函数args等),例如:

    map_stdin() {
      local FUNCTION=$1
      while read LINE; do
        $FUNCTION $LINE
      done
    }
    
    square() { echo "$(($1 * $1))"; }
    
    $ echo "1 2 3 4 5" | xargs -n1 | map_stdin square | xargs
    1 4 9 16 25
    
        3
  •  3
  •   lasseoe    15 年前

    或…

    echo "1 2 3 4 5" | xargs -n 1 | while read number 
     do
       echo $((number * number))
     done
    
        4
  •  2
  •   aoakenfo    11 年前
    echo 1 2 3 4 5 | xargs -n 1 expr -1 +
    
        5
  •  1
  •   SiggyF    15 年前

    或者您可以通过管道将表达式连接到BC:

    echo "1 2 3 4 5" | (
      read line; 
      for i in $line;
      do
        echo $i^2 | bc; 
      done; 
      echo
    )
    
        6
  •  1
  •   tilo    15 年前
    echo 1 2 3 4 5 | xargs -n 1 bash -c 'echo $(($1*$1))' args 
    
        7
  •  1
  •   Niko    8 年前

    使用awk是另一个非常紧凑的解决方案

    echo "1 2 3 4 5" | xargs -n1 | awk '{print $1**2}' | xargs
    
        8
  •  0
  •   Amber    15 年前

    如果您喜欢蟒蛇:

    #!/bin/python
    num = input()
    while num:
        print(int(num) + 1) # Whatever manipulation you want
        try:
            num = input()
        except EOFError:
            break
    
        9
  •  0
  •   Bluu    8 年前

    xargs、xargs和xargs

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

    或者,平行:

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

    如果您将管道作为一组标准参数传递,这就简单多了:

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

    甚至:

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

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

        10
  •  -1
  •   Aleks-Daniel Jakimenko-A. wolfrevo    11 年前

    你可能喜欢这样:

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

    或者像这样:

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