
Eu tenho uma função bash simples dividindo dois números:
echo "750/12.5" | bc
Eu gostaria de pegar a saída bc
e anexar /24
e canalizar o resultado para outra instância de bc
.
Algo como:
echo "750/12.5" | bc | echo $1 + "/24" | bc
Onde $1
está o resultado canalizado.
PS: Sei que poderia fazer echo "750/12.5/24" | bc
minha pergunta mais em relação ao acréscimo de texto a um resultado de canal.
Responder1
Consegui isso usando sed
e substituindo o final da linha:
echo "my text" | sed 's/$/ more text/'
Retorna:
my text more text
Seu exemplo:
echo "750/12.5" | bc | sed 's/$/\/24/' | bc
Responder2
Abordagem alternativa:
TL;DR: Use cat
para concatenar com stdin( -
) como argumento. Observe que isso separará seus fluxos concatenados em novas linhas; remova se indesejado.
Infelizmente, essa abordagem é um pouco complicada para o seu caso de uso específico, pois bc
falha se houver uma nova linha no meio da expressão:
$ echo "750/12.5" | bc | cat - <(echo "/24") | bc
60
(standard_in) 2: parse error
Você pode contornar isso excluindo a nova linha do bc
resultado original:
$ echo "750/12.5" | bc | tr -d '\n' | cat - <(echo "/24") | bc
2
No entanto, me deparei com essa questão pesquisando "bash anexado ao pipe" no Google e, no meu caso, na verdadefazerquero essa nova linha entre as concatenações. Então, para aqueles que estão aqui pelo mesmo motivo, use | 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
Responder3
Na opção mais simples, isso é anexado ao fluxo do tubo:
$ echo "750/12.5" | { bc; echo "/24"; }
60
/24
No entanto, isso tem uma nova linha inesperada, para evitar que você precise usar tr:
$ echo "750/12.5" | { bc | tr -d '\n' ; echo "/24"; }
60/24
Ou, dado o fato de que uma expansão de comando remove novas linhas à direita:
$ printf '%s' $( echo "750/12.5" | bc ); echo "/24"
60/24
Mas provavelmente, a maneira correta deveria ser semelhante a:
$ echo "$(echo "750/12.5" | bc )/24"
60/24
Que, para ser usado em bc, poderia ser escrito assim:
$ bc <<<"$(bc <<<"750/12.5")/24"
2
O que, para obter uma precisão razoável de número flutuante, deve ser algo como:
$ bc <<<"scale=10;$(bc <<<"scale=5;750/12.5")/24"
2.5000000000
Observe a necessidade de duas escalas, pois existem duas instâncias de bc.
É claro que uma instância de bc precisa apenas de uma escala:
$ bc <<<"scale=5;750/12.5/24"
Na verdade, o que você deveria estar pensando é em termos de uma string:
$ a=$(echo "750/12.5") # capture first string.
$ echo "$a/24" | bc # extend the string
2
O comentário sobre a escala acima ainda é válido aqui.
Responder4
Você pode usar awk
para inserir/anexar qualquer coisa ao pipe:
$ date | awk 'BEGIN{print "prefix line"} {print} END{print "suffix line"}'
prefix line
Mo 21. Aug 15:24:30 CEST 2023
suffix line
onde
date
- é o seu canal de entrada (data atual, por exemplo aqui)BEGIN{print "prefix line"}
- este bloco irá inserir a saída antes do principal{print}
- imprime o conteúdo do pipe de entrada; alguém poderia fazer algum processamento aqui, se necessárioEND{print "suffix line"}
- anexa a saída após main
Para fazer o mesmo em linha única, basta usar 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