Estou procurando um comando que aceite (como entrada) várias linhas de texto, cada linha contendo um único inteiro e produza a soma desses números inteiros.
Como pano de fundo, tenho um arquivo de log que inclui medições de tempo. Através do grepping para as linhas relevantes e um pouco de sed
reformatação, posso listar todas as temporizações nesse arquivo. Eu gostaria de calcular o total. Eu posso canalizar essa saída intermediária para qualquer comando para fazer a soma final. Eu sempre usei expr
no passado, mas, a menos que seja executado no modo RPN, não acho que vai lidar com isso (e mesmo assim seria complicado).
Como posso obter a soma dos números inteiros?
Respostas:
Um pouco de awk deve fazer isso?
Nota: algumas versões do awk têm comportamentos estranhos se você adicionar algo que exceda 2 ^ 31 (2147483647). Veja os comentários para mais informações. Uma sugestão é usar em
printf
vez deprint
:fonte
ls $@ | xargs -i pdftk {} dump_data | grep NumberOfPages | awk '{s+=$2} END {print s}'
awk '{s+=$1} END {printf "%.0f", s}' mydatafile
vez disso.Colar normalmente mescla linhas de vários arquivos, mas também pode ser usado para converter linhas individuais de um arquivo em uma única linha. O sinalizador delimitador permite passar uma equação do tipo x + x para bc.
Como alternativa, ao canalizar a partir de stdin,
fonte
paste
pode usar um traço-
como o nome do arquivo - o que lhe permitirá canalizar os números da saída de um comando para a saída padrão da pasta, sem a necessidade de criar um arquivo primeiro:<commands> | paste -sd+ - | bc
-
, porém. (É útil se você quiser combinar um arquivo com o stdin).A versão one-liner no Python:
fonte
python -c"import sys; print(sum(map(int, sys.stdin)))"
find . -name '*.epub' -exec stat -c %s '{}' \; | python -c "import sys; nums = [int(n) for n in sys.stdin if int(n) < 10000000]; print(sum(nums)/len(nums))"
import sys; print(sum(int(''.join(c for c in l if c.isdigit())) for l in sys.stdin))
Eu colocaria um grande aviso sobre a solução comumente aprovada:
isso ocorre porque, neste formulário, o awk usa uma representação inteira assinada de 32 bits: ele excederá as somas que excedem 2147483647 (ou seja, 2 ^ 31).
Uma resposta mais geral (para somar números inteiros) seria:
fonte
echo -e "2147483647 \n 100" |awk '{s+=$1}END{print s}'
shows2147483747
echo 999999999999999999 | awk '{s+=$1} END {printf "%.0f\n", s}'
produz1000000000000000000
Festa simples:
fonte
num
definido? Eu acredito que de alguma forma está ligado à< numbers.txt
expressão, mas não está claro como.Observe que números negativos prefixados com sinal de menos devem ser traduzidos
dc
, pois ele usa_
prefixo em vez de-
prefixo para isso. Por exemplo, viatr '-' '_' | dc -f- -e '...'
.Edit: Como esta resposta obteve tantos votos "pela obscuridade", aqui está uma explicação detalhada:
A expressão
[+z1<r]srz1<rp
faz o seguinte :Como pseudo-código:
Para realmente entender a simplicidade e o poder de
dc
, aqui está um script Python funcional que implementa alguns dos comandosdc
e executa uma versão Python do comando acima:fonte
(echo "0"; sed 's/$/ +/' inp; echo 'pq')|dc
.dc -e '0 0 [+?z1<m]dsmxp'
. Portanto, não salvamos todos os números na pilha antes do processamento, mas os lemos e processamos um a um (para ser mais preciso, linha por linha, pois uma linha pode conter vários números). Observe que a linha vazia pode terminar uma sequência de entrada.sed
substituição pode ser removido, poisdc
não se importa com espaços entre argumentos e operadores.(echo "0"; sed 's/$/+/' inputFile; echo 'pq')|dc
Com jq :
fonte
Festança pura e curta.
fonte
f=$(<numbers.txt)
.f=$(cat); echo $(( ${f//$'\n'/+} ))
um script, poderá canalizar qualquer coisa para esse script ou invocá-lo sem argumentos para a entrada stdin interativa (termine com Control-D).<numbers.txt
é uma melhoria, mas, em geral, esta solução é eficiente apenas para pequenos arquivos de entrada; por exemplo, com um arquivo de 1.000 linhas de entrada, aawk
solução aceita é cerca de 20 vezes mais rápida na minha máquina - e também consome menos memória, porque o arquivo não é lido de uma só vez.fonte
Meus quinze centavos:
Exemplo:
fonte
grep -v '^$'
. Obrigado!Fiz uma referência rápida nas respostas existentes que
lua
ourocket
),Sempre adicionei os números de 1 a 100 milhões que eram factíveis na minha máquina em menos de um minuto para várias soluções.
Aqui estão os resultados:
Pitão
Awk
Colar & Bc
Isso ficou sem memória na minha máquina. Funcionou para metade do tamanho da entrada (50 milhões de números):
Então eu acho que levaria aproximadamente 35s para os 100 milhões de números.
Perl
Rubi
C
Apenas para fins de comparação, compilei a versão C e testei isso também, apenas para ter uma idéia de quanto as soluções baseadas em ferramentas são mais lentas.
Conclusão
É claro que C é mais rápido com 8s, mas a solução Pypy adiciona apenas uma sobrecarga muito pequena de cerca de 30% a 11s . Mas, para ser justo, o Pypy não é exatamente padrão. A maioria das pessoas tem apenas o CPython instalado, o que é significativamente mais lento (22s), exatamente tão rápido quanto a solução Awk popular.
A solução mais rápida baseada em ferramentas padrão é o Perl (15s).
fonte
paste
+bc
era exatamente o que eu procurava para somar valores hexadecimais, obrigado!use std::io::{self, BufRead}; fn main() { let stdin = io::stdin(); let mut sum: i64 = 0; for line in stdin.lock().lines() { sum += line.unwrap().parse::<i64>().unwrap(); } println!("{}", sum); }
Forro liso da festança um
fonte
echo $(( $( tr "\n" "+" < /tmp/test) 0 ))
tr
não é exatamente "plain Bash" / procurar defeitosSolução BASH, se você quiser fazer deste um comando (por exemplo, se você precisar fazer isso com frequência):
Então uso:
fonte
Eu acho que AWK é o que você está procurando:
Você pode usar este comando passando a lista de números pela entrada padrão ou passando o arquivo que contém os números como parâmetro.
fonte
O seguinte funciona no bash:
fonte
cat numbers.txt
etapa seria problemática.Você pode usar num-utils, embora possa ser um exagero para o que você precisa. Este é um conjunto de programas para manipular números no shell e pode fazer várias coisas bacanas, incluindo, é claro, adicioná-las. Está um pouco desatualizado, mas eles ainda funcionam e podem ser úteis se você precisar fazer algo mais.
http://suso.suso.org/programs/num-utils/
fonte
numsum numbers.txt
.Sei que essa é uma pergunta antiga, mas gosto dessa solução o suficiente para compartilhá-la.
Se houver interesse, explicarei como funciona.
fonte
Pure bash e em uma linha :-)
fonte
((
parênteses))
?$(< numbers.txt)
fonte
Perl puro alternativo, razoavelmente legível, sem pacotes ou opções necessárias:
fonte
Para os amantes de Ruby
fonte
Não é possível evitar o envio deste:
Pode ser encontrado aqui:
O linux de uma linha mais elegante do shell unix para somar uma lista de números de precisão arbitrária?
E aqui estão suas vantagens especiais sobre o awk, bc e amigos:
fonte
Usando o utilitário GNU
datamash
:Resultado:
Se os dados de entrada forem irregulares, com espaços e tabulações em locais ímpares, isso pode confundir
datamash
, então use o-W
comutador:... ou use
tr
para limpar o espaço em branco:fonte
Minha versão:
fonte
seq -s+ -5 10 | bc
Você pode fazer isso em python, se sentir-se confortável:
Não testado, apenas digitado:
Sebastian apontou um roteiro único:
fonte
cat
é usado para demonstrar que o script funciona tanto para stdin quanto para arquivos em argv [] (comowhile(<>)
em Perl). Se sua entrada estiver em um arquivo, '<' será desnecessário.< numbers.txt
demonstra que ele funciona no stdin tão bem quantocat numbers.txt |
funciona. E isso não ensina maus hábitos.Ou, você pode digitar os números na linha de comando:
No entanto, este comporta o arquivo, portanto, não é uma boa ideia usá-lo em arquivos grandes. Veja a resposta de j_random_hacker, que evita o slurping.
fonte
O seguinte deve funcionar (supondo que seu número seja o segundo campo em cada linha).
fonte
Uma linha na raquete:
fonte
C (não simplificado)
fonte
Pedimos desculpas antecipadamente pela legibilidade dos backticks ("` "), mas eles funcionam em conchas que não sejam o bash e, portanto, são mais fáceis de colar. Se você usa um shell que o aceita, o formato $ (command ...) é muito mais legível (e, portanto, depurável) do que o `command ...` então sinta-se à vontade para modificar sua sanidade.
Eu tenho uma função simples no meu bashrc que usará o awk para calcular vários itens simples de matemática
Isso fará +, -, *, /, ^,%, sqrt, sin, cos, parênteses .... (e mais, dependendo da sua versão do awk) ... você pode até gostar do ponto flutuante printf e format saída, mas isso é tudo que eu normalmente preciso
para esta pergunta em particular, eu simplesmente faria isso para cada linha:
então o bloco de código para somar cada linha ficaria assim:
Isto é, se você quiser somar apenas linha por linha. No entanto, para um total de cada número no arquivo de dados
btw se eu precisar fazer algo rápido na área de trabalho, eu uso o seguinte:
fonte
$()
?