[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
의사 코드로 :
- “add_top_of_stack”을 다음과 같이 정의하십시오.
- 스택에서 두 개의 최상위 값을 제거하고 결과를 다시 추가하십시오.
- 스택에 둘 이상의 값이 있으면 “add_top_of_stack”을 재귀 적으로 실행하십시오.
- 스택에 둘 이상의 값이 있으면 “add_top_of_stack”을 실행하십시오.
- 스택에 남은 유일한 항목 인 결과를 인쇄합니다.
의 단순성과 힘을 실제로 이해하기 위해 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()