[shell] 한 줄에 하나씩 정수를 합하는 쉘 명령?

여러 줄의 텍스트를 입력하고 각 줄에 단일 정수가 들어 있고 이러한 정수의 합계를 출력하는 명령을 찾고 있습니다.

약간의 배경으로, 타이밍 측정을 포함하는 로그 파일이 있습니다. 관련 줄에 대한 grepping과 약간의 sed재 포맷을 통해 해당 파일의 모든 타이밍을 나열 할 수 있습니다. 나는 총계를 해결하고 싶습니다. 최종 합계를 수행하기 위해이 중간 출력을 모든 명령에 파이프 할 수 있습니다. 나는 항상 expr과거에 사용했지만 RPN 모드에서 실행되지 않으면 이것에 대처할 것이라고 생각하지 않습니다 (그리고 심지어 까다로울 것입니다).

정수의 합계를 어떻게 얻을 수 있습니까?



답변

조금 어색해야합니까?

awk '{s+=$1} END {print s}' mydatafile

참고 : 2 ^ 31 (2147483647)을 초과하는 항목을 추가하려는 경우 일부 버전의 awk에서 이상한 동작이 발생합니다. 더 많은 배경에 대한 의견을 참조하십시오. 한 가지 제안은 다음 printf보다는 사용 하는 것입니다 print.

awk '{s+=$1} END {printf "%.0f", s}' mydatafile


답변

붙여 넣기는 일반적으로 여러 파일의 행을 병합하지만 파일의 개별 행을 단일 행으로 변환하는 데 사용될 수도 있습니다. 분리 문자 플래그를 사용하면 x + x 유형 방정식을 bc에 전달할 수 있습니다.

paste -s -d+ infile | bc

또는 stdin에서 배관 할 때

<commands> | paste -s -d+ - | bc


답변

파이썬에서 한 줄짜리 버전 :

$ python -c "import sys; print(sum(int(l) for l in sys.stdin))"


답변

일반적으로 승인 된 솔루션에 큰 경고를 표시합니다.

awk '{s+=$1} END {print s}' mydatafile # DO NOT USE THIS!!

이 형식에서 awk는 32 ​​비트 부호있는 정수 표현을 사용하기 때문에 2147483647 (즉, 2 ^ 31)을 초과하는 합계에 대해 오버 플로우됩니다.

더 일반적인 대답 (정수를 합산하는 경우)은 다음과 같습니다.

awk '{s+=$1} END {printf "%.0f\n", s}' mydatafile # USE THIS INSTEAD


답변

일반 배쉬 :

$ cat numbers.txt
1
2
3
4
5
6
7
8
9
10
$ sum=0; while read num; do ((sum += num)); done < numbers.txt; echo $sum
55


답변

dc -f infile -e '[+z1<r]srz1<rp'

빼기 부호가 붙은 음수 dc_접두사 대신 -접두사를 사용 하기 때문에 로 변환해야 합니다. 예를 들어 tr '-' '_' | dc -f- -e '...'.

편집 :이 답변에 “불명확 한”투표가 너무 많으므로 자세한 설명은 다음과 같습니다.

표현식 [+z1<r]srz1<rp 은 다음을 수행합니다 .

[   interpret everything to the next ] as a string
  +   push two values off the stack, add them and push the result
  z   push the current stack depth
  1   push one
  <r  pop two values and execute register r if the original top-of-stack (1)
      is smaller
]   end of the string, will push the whole thing to the stack
sr  pop a value (the string above) and store it in register r
z   push the current stack depth again
1   push 1
<r  pop two values and execute register r if the original top-of-stack (1)
    is smaller
p   print the current top-of-stack

의사 코드로 :

  1. “add_top_of_stack”을 다음과 같이 정의하십시오.
    1. 스택에서 두 개의 최상위 값을 제거하고 결과를 다시 추가하십시오.
    2. 스택에 둘 이상의 값이 있으면 “add_top_of_stack”을 재귀 적으로 실행하십시오.
  2. 스택에 둘 이상의 값이 있으면 “add_top_of_stack”을 실행하십시오.
  3. 스택에 남은 유일한 항목 인 결과를 인쇄합니다.

의 단순성과 힘을 실제로 이해하기 위해 dc다음 명령 중 일부 명령을 구현 dc하고 위 명령의 Python 버전을 실행하는 작동하는 Python 스크립트가 있습니다 .

### Implement some commands from dc
registers = {'r': None}
stack = []
def add():
    stack.append(stack.pop() + stack.pop())
def z():
    stack.append(len(stack))
def less(reg):
    if stack.pop() < stack.pop():
        registers[reg]()
def store(reg):
    registers[reg] = stack.pop()
def p():
    print stack[-1]

### Python version of the dc command above

# The equivalent to -f: read a file and push every line to the stack
import fileinput
for line in fileinput.input():
    stack.append(int(line.strip()))

def cmd():
    add()
    z()
    stack.append(1)
    less('r')

stack.append(cmd)
store('r')
z()
stack.append(1)
less('r')
p()


답변

JQ :

seq 10 | jq -s 'add' # 'add' is equivalent to 'reduce .[] as $item (0; . + $item)'