Добавить к каналу и передать дальше?

Добавить к каналу и передать дальше?

У меня есть простая функция bash, делящая два числа:

echo "750/12.5" | bc

Я хотел бы взять вывод bc, добавить его /24и передать по конвейеру в другой экземпляр bc.

Что-то вроде:

echo "750/12.5" | bc | echo $1 + "/24" | bc

Где $1находится переданный результат.

PS Я понимаю, что мог бы просто задать echo "750/12.5/24" | bcсвой вопрос, но он больше касается добавления текста к результату конвейера.

решение1

Я добился этого sed, заменив конец строки:

echo "my text" | sed 's/$/ more text/'

Возврат:

my text more text

Ваш пример:

echo "750/12.5" | bc | sed 's/$/\/24/' | bc

решение2

Альтернативный подход:

TL;DR: Используйте catдля конкатенации с stdin ( -) в качестве аргумента. Обратите внимание, что он разделит ваши конкатенированные потоки символами новой строки; удалите, если это нежелательно.

К сожалению, этот подход немного громоздок для вашего конкретного случая использования, поскольку bcне сработает, если в середине выражения есть символ новой строки:

$ echo "750/12.5" | bc | cat - <(echo "/24") | bc
60
(standard_in) 2: parse error

Эту проблему можно обойти, удалив символ новой строки из исходного bcрезультата:

$ echo "750/12.5" | bc | tr -d '\n' | cat - <(echo "/24") | bc
2

Однако я наткнулся на этот вопрос, загуглив «bash append to pipe», и в моем случае я на самом деледелатьхотите эту новую строку между конкатенациями. Так что для тех, кто здесь по той же причине, используйте | cat - <(...):

$ echo foo | cat - <(echo bar)
foo
bar
$ echo foo | cat - <(echo bar) | sort | cat - <(echo last_line)
bar
foo
last_line
$ echo foo | cat - <(echo bar) | sort | cat <(echo header) - <(echo last_line)
header
bar
foo
last_line

решение3

В простейшем варианте это добавляется к потоку канала:

$ echo "750/12.5" | { bc; echo "/24"; }
60
/24

Однако здесь есть неожиданный перевод строки, чтобы избежать этого, вам нужно использовать tr:

$ echo "750/12.5" | { bc | tr -d '\n' ; echo "/24"; }
60/24

Или, учитывая тот факт, что расширение команды удаляет конечные символы новой строки:

$ printf '%s' $( echo "750/12.5" | bc ); echo "/24"
60/24

Но, вероятно, правильный способ должен быть примерно таким:

$ echo "$(echo "750/12.5" | bc )/24"
60/24

Что, если использовать в до н.э., можно записать так:

$ bc <<<"$(bc <<<"750/12.5")/24"
2

Что, для получения разумной точности числа с плавающей точкой, должно быть примерно так:

$ bc <<<"scale=10;$(bc <<<"scale=5;750/12.5")/24"
2.5000000000

Обратите внимание на необходимость двух шкал, поскольку имеются два примера bc.

Конечно, для одного экземпляра bc требуется только одна шкала:

$ bc <<<"scale=5;750/12.5/24"

На самом деле, вам следует думать о строке:

$ a=$(echo "750/12.5")        # capture first string.
$ echo "$a/24" | bc           # extend the string
2

Замечание о масштабе, сделанное выше, здесь все еще актуально.

решение4

Вы можете использовать awkдля вставки/добавления чего-либо в канал:

$ date | awk 'BEGIN{print "prefix line"} {print}  END{print "suffix  line"}'
prefix line
Mo 21. Aug 15:24:30 CEST 2023
suffix  line

где

  • date- это ваш входной канал (текущая дата, например, здесь)
  • BEGIN{print "prefix line"}- этот блок вставит вывод перед основным
  • {print}- выводит содержимое входного канала; при необходимости здесь можно выполнить некоторую обработку
  • END{print "suffix line"} - это добавляет вывод после основного

Чтобы сделать то же самое в одной строке, просто используйте printf:

$ date | awk 'BEGIN{printf("prefix line >> ")} {printf($0)}  END{printf(" << suffix  line")}'
prefix line >> Mo 21. Aug 15:32:08 CEST 2023 << suffix  line/upload/sc505enb/tmp>

$ echo "750/12.5" | bc | awk '{printf($0)}  END{printf("/24\n")}'
60/24

Связанный контент