텍스트 파일의 데이터 복잡성을 줄입니다.

텍스트 파일의 데이터 복잡성을 줄입니다.

나는 이 파일을 가지고 있습니다 :

  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

관련 정보