여러 열을 합산하려는 시나리오가 있습니다.
파일의 데이터는 다음과 같습니다.
ID|NAME|SAL|COST|PER|TAG
1|A|10|10|20|10|
1|B|10|15|20|10|
1|C|10|17|25|80|
1|D|115|110|20|100|
1|E|10|10|10|10|
COLUMN - SAL 태그의 총 비용을 원합니다 |
간단한 명령어로 하나 만들었는데 함수를 만들어서 어떻게 하는지
awk '{FS="|"}{s+=$3}END{print s}' file.txt
함수는 열 이름을 전달할 때 해당 열의 합계를 계산하도록 매개변수화되어야 합니다.
합계 열은 다를 수 있습니다. 두 개의 열 합계만 필요한 경우 두 개의 열 이름을 가져와 해당 합계를 처리해야 하는 것과 같은 요구 사항이 될 수 있습니다.
답변1
awk
입력 문자열에서 공백을 사용 하고 잃습니다.
myv='SAL|COST|PER|TAG'
awk -v ar="$myv" '
BEGIN{FS="|"; getline; for (i=1;i<=NF;i++) {if ($i ~ ar) head[i]=0;title[i]=$i}}
NF>1{for (h in head) head[h]+=$h}
END{for (h in head) print title[h]":\t"head[h]}
' file
이는 정규식 일치가 고유하다고 가정합니다. 그렇지 않다면...
myv='SAL|COST|PER|TAG'
awk -v ar="$myv" '
BEGIN{FS="|"; getline; for (i=1;i<=NF;i++) head[$i]=i; split(ar,titles,"|")}
NF>1{for (i=1; i<=NF; i++) val[i]+=$i}
END{for (t in titles) print titles[t]":\t"val[head[titles[t]]]}
' file
산출
SAL: 155
COST: 162
PER: 95
TAG: 210
답변2
최신 버전을 사용하세요.밀러
$ mlr --csvlite --allow-ragged-csv-input --fs '|' stats1 -a sum -f SAL file.txt
SAL_sum
155
(입력하신 내용이 최신 버전이므로 최신 버전만 필요합니다.떨어진즉, 헤더에 해당 이름이 없는 빈 열이 뒤에 있습니다. 쉼표로 구분된 목록으로 이름을 옵션에 전달하여 Miller에서 여러 열을 쉽게 합산할 수 있습니다 -f
.
... stats1 -a sum -f SAL,COST,PER,TAG ...
비슷하다GNU 데이터 혼합
$ datamash -Ht '|' sum SAL,COST,PER,TAG < file.txt
sum(SAL)|sum(COST)|sum(PER)|sum(TAG)
155|162|95|210
답변3
~에서 영감을 얻다https://stackoverflow.com/a/32616101:
$ col=SAL
$ colnum=$(awk -v RS='|' '/'$col'/{ print NR; exit}' testfile)
$ awk '{FS="|"}{s+='$colnum'}END{print s}' testfile
18
여기서의 비결은 인용입니다. 변수는 작은따옴표 밖에 있습니다.
이는 스크립트로 쉽게 캡슐화됩니다 sumcols.sh
.
#!/bin/bash
FILE="$1"
COLUMNS="${@:2}"
for col in $COLUMNS; do
colnum=$(awk -v RS='|' '/'$col'/{ print NR; exit}' $FILE)
awk '{FS="|"}{s+='$colnum'}END{print "'$col' ", s}' $FILE
done | column -t
처리할 파일을 첫 번째 위치 인수로 호출하고 그 뒤에 처리할 열을 호출합니다. 예를 들어:
$ ./sumcols.sh testfile SAL COST
SAL 18
COST 24