BASH: как выполнить арифметику по числам в трубе - PullRequest
7 голосов
/ 17 июля 2010

Я получаю поток чисел в канале и хотел бы выполнить некоторые операции, прежде чем передавать их в следующий раздел, но я немного растерялся, как бы я это сделал, не сломав канал.

например

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

У вас есть какие-нибудь идеи о том, как сделать что-то подобное этой работе?Фактическая операция, которую я хочу выполнить - это просто добавить по одному к каждому номеру.

Ответы [ 10 ]

7 голосов
/ 17 июля 2010
echo 1 2 3 4 5|{
  read line; 
  for i in $line;
  do
    echo -n "$((i * i)) "; 
  done; 
  echo
}

{} создает группировку.Вместо этого вы можете создать скрипт для этого.

4 голосов
/ 17 июля 2010

Я бы написал:

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

Мы можем думать об этом как о «карте» (функциональное программирование). Существует много способов написания функции map в bash (используя stdin, function 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 голосов
/ 05 октября 2014
echo 1 2 3 4 5 | xargs -n 1 expr -1 +
3 голосов
/ 17 июля 2010

Или ..

echo "1 2 3 4 5" | xargs -n 1 | while read number 
 do
   echo $((number * number))
 done
1 голос
/ 27 июня 2017

Использование awk - еще одно довольно компактное решение

echo "1 2 3 4 5" | xargs -n1 | awk '{print $1**2}' | xargs
1 голос
/ 17 июля 2010
echo 1 2 3 4 5 | xargs -n 1 bash -c 'echo $(($1*$1))' args 
1 голос
/ 17 июля 2010

Или вы можете передать выражение в bc:

echo "1 2 3 4 5" | (
  read line; 
  for i in $line;
  do
    echo $i^2 | bc; 
  done; 
  echo
)
0 голосов
/ 08 ноября 2017

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

0 голосов
/ 01 ноября 2014

Йой может понравиться что-то вроде этого:

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 / /, $_'
0 голосов
/ 17 июля 2010

Если вы предпочитаете Python:

#!/bin/python
num = input()
while num:
    print(int(num) + 1) # Whatever manipulation you want
    try:
        num = input()
    except EOFError:
        break
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...