
У меня есть простая функция 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