나는 이 파일을 가지고 있습니다 :
1 2
2 7
3 4
4 7
5 3
6 7
7 1
8 2
9 4
내가 원하는 출력은
1 13
2 17
3 7
내 입력에는 9개의 행이 있는데 두 번째 열에 합계를 유지하면서 3개의 행으로 줄이려고 합니다. 예를 들어 첫 번째 열의 1은 두 번째 열의 1,2,3, 13을 나타내고 첫 번째 행은 덧셈(2+4+7)을 나타내는 식입니다. 어떤 아이디어가 있나요? awk/perl 또는 기타 Linux 도구를 사용할 수 있습니다.
답변1
해결책 은 다음과 같습니다 awk
.
awk '{ s+=$2; if (!(NR%3)) { k++; print k,s; s=0 } };
END { if (NR%3) { k++; print k, s } }' file.txt
첫 번째 열을 무시하고 이를 k
출력 행 번호로 생성하는 것을 선호합니다. 두 번째 열이 합산되어 s
세 번째 행( (NR % 3) == 0
)마다 출력되고 누산기가 재설정됩니다. 마지막으로 남은 행이 있으면 나머지 합계를 출력합니다.
샘플 파일 출력
1 13
2 17
3 7
완전성을 위해 여기에마른모듈로-3 및 END 블록에서 중복 코드를 처리하는 함수를 사용하는 버전:
awk 'function outsum() { print ++k,s; s=0 };
{ s+=$2; if (!(NR%3)) { outsum() } };
END { if (NR%3) { outsum() } }' file.txt
답변2
펄 솔루션:
perl -lane '
$s += $F[1];
print(join "\t", ++$l, $s), $s = 0
if 0 == $. % 3 || eof;
' input-file
-n
입력을 한 줄씩 읽습니다.-a
공백의 각 줄을 @F 배열로 분할합니다.$s
합계를 저장하는 변수로 사용됨$.
입력 줄 번호를 포함하는 특수 변수입니다.$l
출력 라인 번호입니다
답변3
이건 아마도 가야 할 것 같아요코드 골프. 이건 안감이에요아니요 perl
, awk
또는 sed
:
paste <(for i in $(seq 1 0.33333333334 $(A=$(wc -l input.dat | cut -d ' ' -f 1); echo $A/3+1 | bc)); do echo $i/1 | bc; done) <(tr -s ' ' < input.dat | cut -d ' ' -f 3) | datamash -g 1 sum 2
상세한
왼쪽
for i in $(seq 1 0.33333333334 $(A=$(wc -l input.dat | cut -d ' ' -f 1); echo $A/3+1 | bc)); do echo $i/1 | bc; done
유사한 목록을 생성합니다(입력 파일의 실제 줄 수를 설명).
1
1
1
2
2
2
3
3
3
그리고 오른쪽
tr -s ' ' < input.dat | cut -d ' ' -f 3
입력 파일의 첫 번째 열을 자르고 다음을 남겨 둡니다.
2
7
4
7
3
7
1
2
4
paste
그것들을 다시 모아서datamash
~이든그룹화 기준.
답변4
이것은 쉘 명령 전용 버전입니다. 행으로 나누었지만 단일 행으로 함께 스크롤할 수 없는 이유는 없습니다(그렇게 시작되었습니다).
(
s=0 k=1 n=0
while read x v
do
s=$((s+v)) n=$((n+1))
if [[ n -eq 3 ]]
then
echo $k $s
k=$((k+1)) n=0 s=0
fi
done
[[ s -gt 0 ]] && echo $k $s
) <file.txt
( s=0 k=1 n=0; while read x v; do s=$((s+v)) n=$((n+1)); if [[ n -eq 3 ]]; then echo $k $s; k=$((k+1)) n=0 s=0; fi; done; [[ s -gt 0 ]] && echo $k $s ) <file.txt