도와주세요? 나에겐 임무가 있다. 숫자가 포함된 텍스트를 입력했습니다. 예를 들어:
beta 1
score 9
something 2
beta 4
something 1
주위에 같은 텍스트가 있는 모든 숫자를 세어야 합니다. 내 출력은 다음과 같습니다. (이 방법으로 ":"을 사용하십시오)
beta:5
something:3
score:9
또한, 점수를 저장하는 임시 파일에 문제가 있을 수 있습니다. mktemp
스크립트가 완료된 후 삭제하는 데 사용해야 합니다 . 도와주세요, 감사합니다.
답변1
입력에는 항상 한 줄에 두 개의 필드가 포함되어 있다고 가정합니다.
GNU 유틸리티를 사용하여 datamash
데이터를 정렬하고, 첫 번째 필드별로 그룹화하고, 각 그룹에 대한 두 번째 필드의 합계를 계산할 수 있습니다.
datamash -s -W --output-delimiter=: groupby 1 sum 2 <file
여기에서는 유틸리티가 연속 공백 문자를 필드 구분 기호로 처리하고 출력 구분 기호를 해당 문자 로 설정하도록 -s
입력이 정렬됩니다 . 나머지는 첫 번째 필드를 기준으로 그룹화하고 각 그룹에 대한 두 번째 필드의 합계를 계산하도록 지시합니다.-W
--output-delimiter=:
:
datamash
라는 파일의 문제에 대한 입력이 주어지면 file
다음과 같은 출력이 생성됩니다.
beta:5
score:9
something:3
다른 여러 가지 방법으로도 이 문제를 해결할 수 있습니다. 가장 간단한 계산 솔루션은 다음을 사용하는 것입니다 awk
.
awk '{ sum[$1] += $2 } END { for (key in sum) printf "%s:%d\n", key, sum[key] }' file
sum
여기서는 첫 번째 필드에 있는 각 문자열의 합계를 유지하기 위해 연관 배열을 사용합니다 . 이 END
블록은 입력이 끝나면 실행되며 계산된 합계를 문자열과 함께 출력합니다.
또한 이 솔루션은 질문에 표시된 것처럼 첫 번째 필드가 공백 문자를 포함하지 않는 단일 단어라고 가정합니다.
쉘 루프를 사용하여 원본 파일에서 정렬된 행을 읽고 새로운 첫 번째 필드가 나타날 때마다 두 번째 필드의 합계를 인쇄하고 재설정합니다.
unset -v prev
sort file |
{
while read -r key value; do
if [ "$key" != "${prev-$key}" ]; then
# prev is set and different from $key
printf '%s:%d\n' "$prev" "$sum"
sum=0
fi
prev=$key
sum=$(( sum + value ))
done
if [ "${prev+set}" = set ]; then
printf '%s:%d\n' "$prev" "$sum"
fi
}
답변2
대용량 파일을 처리하는 경우 키와 값을 저장하기 위해 RAM에 거대한 배열을 할당하지 않도록 sort
및 사용을 고려하세요.awk
λ cat input.txt
beta 1
score 9
something 2
beta 4
something 1
sort input.txt |
awk -v OFS=: 'NR==1{ key=$1 }; NR>1&&$1!=key{ print key, sum; sum=0; key=$1 }; {sum+=$2} END{ print key, sum}'
beta:5
score:9
something:3
답변3
#!/bin/bash
declare -i SECOND
while read first second; do
if [ -z $FIRST ] || [ $first = $FIRST ]; then
SECOND+=second
else
echo $FIRST:$SECOND
SECOND=second
fi
FIRST=$first
done < <(sort file)
echo $FIRST:$SECOND
일반적으로 나는 비슷한 공백을 작성하고 프로덕션에서 모든 변수를 따옴표로 묶습니다.
답변4
for k in $(awk '{if(!seen[$1]++)print $1}' file.txt); do awk -v k="$k" 'BEGIN{sum=0}$0 ~ k {sum=sum+$2}END{print k,sum}' file.txt; done
산출
beta 5
score 9
something 3