다음과 같은 데이터 파일이 있다고 가정해 보겠습니다.
111 222 333
444 555 666
777 888 999
GNU Datamash를 사용하여 다음과 같이 각 열의 합계를 계산할 수 있습니다.
cat foo | datamash -t\ sum 1 sum 2 sum 3
1332 1665 1998
데이터 파일의 열 수를 모르는 경우 datamash를 사용하여 이 작업을 어떻게 수행합니까?
예를 들어 필드 선택기 cut
와 같은 범위 종료 기호를 지원하기 때문에 이 질문을 하는 것입니다 .-
답변1
알 수 없는 범위를 지정하는 옵션이 표시되지 않습니다.데이터 혼합 핸드북
이 perl
단 하나의 라이너를 사용해보십시오
$ perl -lane '$s[$_]+=$F[$_] for 0..$#F; END{print join " ", @s}' ip.txt
1332 1665 1998
-a
옵션은 자동으로 입력 줄을 공백으로 분할하고 결과를@F
배열 에 저장합니다.for 0..$#F
배열을 반복하여$#F
마지막 요소의 인덱스 제공$s[$_]+=$F[$_]
합계를@s
배열에 저장하면 기본적으로 초기 값은0
숫자 컨텍스트에 있습니다.$_
각 반복에는 인덱스 값이 있습니다.END{print join " ", @s}
모든 입력 행이 처리된 후@s
공백을 구분 기호로 사용하여 배열 내용을 인쇄합니다.
답변2
cols=$( awk '{print NF; exit}' foo); cat foo | datamash -t\ sum 1-$cols
또는
cat foo | datamash -t\ sum 1-$( awk '{print NF; exit}' foo)
datamash
열 범위를 지정하는 기능이 있으므로 열 수를 계산하고 그 결과를 범위 지정의 일부로 사용합니다. 내 예제 솔루션에서는 awk
파일의 첫 번째 줄을 확인하고 종료했지만 자신에게 적합한 다른 항목을 사용할 수 있습니다. 출력에 열 번호가 포함된 datamash
함수 자체가 있지만 -check
해당 형식에서는 여전히 관심 있는 특정 숫자를 구문 분석해야 합니다.
답변3
잘 모르겠지만 해결책 datamash
은 다음과 같습니다 awk
.
$ awk '{ for( col=1; col<=NF; col++ ) { totals[col]+=$col } } END { for( col=0; col<length(totals); col++ ) {printf "%s ", totals[col]}; printf "\n" } ' input
1332 1665 1998
awk
이 스크립트를 더 읽기 쉽게 만들려면 다음을 수행하세요 .
{ // execute on all records
for( col=1; col<=NF; col++ ) {
totals[col]+=$col
};
}
END { // execute after all records processed
for( col=0; col<length(totals); col++ ) {
printf "%s ", totals[col]
};
printf "\n";
}
답변4
사용 datamash
및 bash
:
n=($(datamash -W check < foo)); datamash -W sum 1-${n[2]} < foo
산출:
1332 1665 1998
작동 방식:
datamash -W check < foo
출력 문자열"3개의 행, 3개의 필드".n=($(datamash -W check < foo))
문자열을 배열로 로드합니다$n
. 우리는 필드 수, 즉${n[2]}
.datamash -W sum 1-${n[2]} < foo
나머지는 완료되었습니다.
이 작업은 다음을 통해 수행할 수도 있습니다.POSIX쉘 printf
에서는 배열 대신 복잡한 형식의 문자열을 사용하지만 더 조잡합니다.
datamash -W sum 1-$(printf '%0.0s%0.0s%s%0.0s' $(datamash -W check < foo)) < foo
이 작업은 셸 도구를 사용하여 수행할 수도 있습니다.
datamash -W sum 1-$(head -1 foo | wc -w) < foo