별도의 입력 파일에서 특정 행 범위에 대한 열 평균을 계산합니다.

별도의 입력 파일에서 특정 행 범위에 대한 열 평균을 계산합니다.

한 파일에 지정된 특정 범위에 대한 평균을 계산하고 이를 다른 파일의 숫자에 적용하려고 합니다. 동시에 두 개의 개별 파일의 정보를 bash에서 사용하는 예를 찾을 수 없습니다. 이것이 내가 하고 싶은 일이다:

첫 번째 파일은 평균을 구하려는 범위를 지정합니다.

범위.txt

Sc0  1  5
Sc1  69 72

두 번째 파일에는 세 번째 열을 사용하여 평균을 구하는 데 필요한 숫자가 포함되어 있습니다.

모든번호.txt

Sc0 1   30
Sc0 2   40
Sc0 3   40
Sc0 4   50
Sc0 5   10
Sc0 6   30
Sc1 69  40
Sc1 70  10
Sc1 71  20
Sc1 72  30

이것이 내가 원하는거야: 평균.txt

34
25

아래에 표시된 bash 루프에서 이 작업을 수행하려고 합니다. 하지만 저는 bash 스크립팅을 처음 접한 상태이므로 이 코드는 작동하지 않습니다.

#!/bin/bash

count=0;
total=0;
  
while read rangeName rangeStart rangeStop            #make column variables for range.txt 
    while read name position sum                     #make column variables for allNumbers.txt                        
        while [$rangeName == $name && $rangeStart < $position <= $rangeStop]; do
            for i in $sum; do
                total=$(echo $total+$i | bc)
                ((count++))
            done
            echo "$total / $count" | bc          #print out averages
        done     
    done < allNumbers.txt
done < ranges.txt

누구든지 이 문제를 해결하도록 도와줄 수 있나요? 미리 감사드립니다.

답변1

실제로 이를 위해 쉘을 사용하고 싶지 않습니다. 첫째, 부동 소수점 연산을 수행하지 않기 때문에 호출 bc하거나 다른 것을 수행해야 합니다. 둘째, 보시다시피 구문이 매우 복잡하기 때문입니다.느린. 바라보다쉘 루프를 사용하여 텍스트를 처리하는 것이 왜 나쁜 습관으로 간주됩니까?자세한 내용은.

거의 모든 다른 언어가 더 좋지만 사용할 수 있는 한 가지 접근 방식은 다음과 같습니다 awk.

$ awk 'NR==FNR{a[$1]["start"]=$2; a[$1]["end"]=$3; next}
       { 
        if($2>=a[$1]["start"] && $2<=a[$1]["end"]){
            values[$1]+=$3; 
            nums[$1]++;
        }
       }
       END{
        for(range in values){
            print values[range]/nums[range]
        }
       }' ranges allNumbers
34
25

이는 주석이 달린 스크립트와 동일합니다.

#!/bin/awk -f

## If we are reading the first file
NR==FNR{
  ## $1 is the range name, so this will save the
  ## start position for this range name as a[$1]["start"] and
  ## the end position as a[$1]["end"]
  a[$1]["start"]=$2;
  a[$1]["end"]=$3;
  ## skip to the next line 
  next
}
## This will only run for the second file
{
  ## If this value falls in the relevant range
  if($2>=a[$1]["start"] && $2<=a[$1]["end"]){
    ## Sum the values of this range and save
    ## in the values array
    values[$1]+=$3;
    ## Count the number of values for this range and save
    ## in the 'nums' array.
    nums[$1]++;
  }
}
## After we've read both files
END{
  ## For each range in the 'values' array
  for(range in values){
    ## print the average
    print values[range]/nums[range]
  }
}

첫 번째 코드 줄을 실행하거나 위의 코드를 저장하여 foo.awk실행 가능하게 만들고 실행할 수 있습니다.

foo.awk ranges allNumbers 

관련 정보