여러 부동 소수점 열의 합계를 계산하는 방법

여러 부동 소수점 열의 합계를 계산하는 방법

부동 소수점 데이터가 포함된 여러 열의 합계를 계산하려는 시나리오가 있습니다.

아래 코드는 정수 값에는 작동하지만 부동 페인트 값에는 작동하지 않습니다.

코드가 이 데이터에 완벽하게 들어맞습니다.

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|

암호:

#!/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

위 코드를 사용하여 다음 데이터의 합계를 어떻게 얻을 수 있습니까?

ID|NAME|SAL|COST|PER|TAG

    1|A|9.234|123.12|20.123|67.1|

    1|B|10.12|153.234|20.90|190.34|

    1|C|8.234|17.01|25.777|80.09|

    1|D|11.2|11.222|10.1|10.00000|

    1|E|16.23|10.1|145.22|11.77278|

새 코드가 작동하지 않습니다.

#!/bin/bash
FILE="$1"
COLUMNS="${@:2}"
for col in $COLUMNS; do
            awk -F'|' '{T+=$col} END { printf "%.10f\n", T }' $FILE
    done | column -t

답변1

처음에는 쉘에서 이 작업을 수행하지 마십시오. 그러나 awk.쉘에서는 부동 소수점 연산을 수행하는 방법을 모릅니다.

귀하의 스크립트는 구문 분석할 파일 이름과 고려할 필드 이름에 해당하는 매개변수 세트를 사용하는 것으로 보입니다.

awk각 열에 대해 두 번 호출하는 것보다 더 효율적으로 이 작업을 수행할 수 있습니다.

BEGIN { OFS = FS = "|" }

FNR == 1 {
        # Handle the header row. Assuming "cols" is a FS-separated
        # string of column names that we want to sum, pick out the
        # column numbers that we want to process and put them in the
        # array "col". This also converts the "cols" string into a
        # corresponding "header" array.

        nf = split(cols, header)
        for (i = 1; i <= NF; ++i)
                for (j = 1; j <= nf; ++j)
                        if ($i == header[j])
                                col[j] = i
        next
}

{
        # Sum each column that we have enumerated in the "col" array.

        for (i = 1; i <= nf; ++i)
                sum[i] += $(col[i])
}

END {
        # Output a two row table containing only the headers that we
        # have summed over and the accumulated sums.

        $0 = ""

        for (i = 1; i <= nf; ++i)
                $i = header[i]
        print

        for (i = 1; i <= nf; ++i)
                $i = sum[i]
        print
}

다음을 사용하여 첫 번째 파일에서 이 명령을 실행하세요.

$ awk -v cols="SAL|COST|PER|TAG" -f script.awk file1
SAL|COST|PER|TAG
155|162|95|210

동일한 열을 두 번 나열하면 두 가지 합계가 발생합니다.

$ awk -v cols="SAL|SAL" -f script.awk file1
SAL|SAL
155|155

두 번째 파일에서:

$ awk -v cols="SAL|COST|PER|TAG" -f script.awk file2
SAL|COST|PER|TAG
55.018|314.686|222.12|359.303

사용 후 처리 column -t:

$ awk -v cols="SAL|COST|PER|TAG" -f script.awk file2 | column -s '|' -t
SAL     COST     PER     TAG
55.018  314.686  222.12  359.303

이것을 간단한 스크립트에 넣으십시오.

#!/bin/sh

infile=$1
shift

IFS='|'

awk -v cols="$*" -f script.awk "$infile" |
column -s '|' -t

다음과 같이 사용할 수 있습니다.

$ ./script.sh file1 PER TAG
PER  TAG
95   210

CSVkit과 같은 CSV 인식 도구를 사용하여 작업을 수행할 수도 있습니다.

csvstatCSV 파일에 대한 몇 가지 기본 "통계"를 계산하는 기능. 파일이 올바른 형식의 CSV 파일이라고 가정하면(각 데이터 행에 후행 |구분 기호가 있으므로 그렇지 않음) 각 열의 합계가 전달될 수 있습니다.

$ csvstat --sum file1
  1. ID: None
  2. NAME: None
  3. SAL: 155
  4. COST: 162
  5. PER: 95
  6. TAG: 210
$ csvstat --sum file2
  1. ID: None
  2. NAME: None
  3. SAL: 55.018
  4. COST: 314.686
  5. PER: 222.12
  6. TAG: 359.30278

또는 단일 열의 경우:

$ csvstat --sum -c 'SAL' file2
55.018

답변2

내 솔루션이 작동합니다

이 데이터세트 1의 경우 - 테스트해 보세요.

ID|NAME|SAL|COST|PER|TAG
1"|"A"|"50.1123"|"10.1"|"25.22"|"10.2"|"
2"|"B"|"50.11"|"15.45"|"25.1"|"10.1118"|"

이 데이터세트 2의 경우 - 테스트해 보세요.

ID|NAME|SAL|COST|PER|TAG
1|A|9.234|123.12|20.123|67.1
2|B|10.12|153.234|20.90|190.34
3|C|8.234|17.01|25.777|80.09
4|D|11.2|11.222|10.1|10.00000
5|E|16.23|10.1|145.22|11.77278

효과적인 솔루션

FILE_NAME="$1"
COLUMN_NAME="$2"

alpha=( $(awk -F"|" 'NR==1{for(i=1;i<=NF;i++){if ($i ~ /'$COLUMN_NAME'/){print i;}}}' $FILE_NAME) )

for each in "${alpha[@]}"
do
      #echo "$each"
      awk -F'"?\\|"?' '{T+=$('$each')} END { printf "%.4f\n", T }' $FILE_NAME
done

이렇게 달리다

bash script.sh DEMO.txt 'SAL|COST|PER|TAG'

출력 1:

100.2223
25.5500
50.3200
20.3118

출력 2:

55.0180
314.6860
222.1200
359.3028

관련 정보