사랑하는 여러분 저에겐 하나 있어요큰데이터 파일은 다음과 같이 말할 수 있습니다.파일.dat, 두 개의 열이 포함되어 있습니다.
예를 들어 file.dat(여러 줄 표시)
0.0000 -23.4334
0.0289 -23.4760
0.0578 -23.5187
0.0867 -23.5616
0.1157 -23.6045
0.1446 -23.6473
0.1735 -23.6900
0.2024 -23.7324
0.2313 -23.7745
0.2602 -23.8162
0.2892 -23.8574
0.3181 -23.8980
0.3470 -23.9379
0.3759 -23.9772
0.4048 -24.0156
0.4337 -24.0532
0.4627 -24.0898
0.4916 -24.1254
note: data file has a blank line at the end of the file
기대되는 성과
열(예: 열 1)에서 최대값과 최소값을 찾거나 추출하고 싶습니다.
max - 0.4916
min - 0.0000
2열과 동일
max - -23.4334
min - -24.1254
불완전한 해(2열에는 적용되지 않음)
열 1의 경우
awk 'BEGIN{min=9}{for(i=1;i<=1;i++){min=(min<$i)?min:$i}print min;exit}' file.dat
0.0000
cat file.dat | awk '{if ($1 > max) max=$1}END{print max}'
0.4916
2열의 경우
awk 'BEGIN{min=9}{for(i=2;i<=2;i++){min=(min<$i)?min:$i}print min;exit}' file.dat
-23.4334
cat file.dat | awk '{if ($2 > max) max=$2}END{print max}'
**no output showing**
질문
2열의 최소값과 최대값을 찾는 데 도움을 주세요. 참고: 데이터 파일 끝에 빈 줄이 있습니다.
답변1
코드의 문제,
awk 'BEGIN{min=9}{for(i=2;i<=2;i++){min=(min<$i)?min:$i}print min;exit}' file.dat
... exit
입력의 첫 번째 줄을 처리한 후 즉시 수행하는 작업입니다. 중간 블록이 트리거되어야 합니다.모든철사. 그런 다음 END
블록에서 찾은 값을 인쇄할 수 있습니다. 다른 코드 조각에서 이 작업을 수행할 수 있습니다.
awk '{if ($1 > max) max=$1}END{print max}'
또 다른 문제는 min
초기화에 마법의 숫자를 사용한다는 것입니다(인용한 첫 번째 코드에서는 9, 두 번째 코드에서는 0, 명시적으로 초기화되지 않은 변수가 계산에 사용되는 경우 해당 값은 0입니다). 이 매직넘버가 실제 데이터의 수치범위를 벗어나면 계산된 최소값 및/또는 최대값이 틀리게 됩니다. 최소값과 최대값을 모두 데이터에서 발견된 값으로 초기화하는 것이 가장 좋습니다.
계속 추적하세요...둘 다최소값과 최대값에는 두 개의 변수가 필요하며 파일의 각 데이터 줄에 대해 이 두 변수를 확인하여 업데이트해야 하는지 확인해야 합니다.
awk
배열이 지원되므로 합계 에 배열을 사용하는 min
것이 자연스럽습니다 max
(열당 하나의 배열 요소). 이것이 제가 아래 코드에서 하고 있는 일입니다.
원하는 수의 열로 일반화합니다.
NF == 0 {
# Skip any line that does not have data
next
}
!initialized {
# Initialize the max and min for each column from the
# data on the first line of input that has data.
# Then immediately skip to next line.
nf = NF
for (i = 1; i <= nf; ++i)
max[i] = min[i] = $i
initialized = 1
next
}
{
# Loop over the columns to see if the max and/or min
# values need updating.
for (i = 1; i <= nf; ++i) {
if (max[i] < $i) max[i] = $i
if (min[i] > $i) min[i] = $i
}
}
END {
# Output max and min values for each column.
for (i = 1; i <= nf; ++i)
printf("Column %d: min=%s, max=%s\n", i, min[i], max[i])
}
이 스크립트와 질문의 데이터를 고려하면 다음과 같습니다.
$ awk -f script.awk file
Column 1: min=0.0000, max=0.4916
Column 2: min=-24.1254, max=-23.4334
첫 번째 블록(모든 행에서 실행됨)의 조건 NF == 0
은 빈 행을 건너뛰는 것입니다. 이 테스트는 "이 행에 데이터 필드(열)가 0개인 경우"를 의미합니다. 이 변수는 initialized
처음부터 0입니다(논리적으로잘못된)이지만 1로 설정됩니다(논리적으로는진짜) 데이터의 첫 번째 줄을 읽은 후.
변수는 초기화하고 값을 지정하는 줄에서 (필드 수) nf
로 초기화됩니다 . NF
이렇게 하면 마지막 행의 필드가 0이더라도 블록의 출력이 제대로 작동합니다.min
max
END
답변2
실제로 모든 지침을 하나의 awk
프로그램으로 결합할 수 있습니다.
awk 'NR==1{min1=max1=$1;min2=max2=$2}\
NR>1 {if ($1<min1) {min1=$1} else if ($1>max1) {max1=$1};\
if ($2<min2) {min2=$2} else if ($2>max2) {max2=$2}; }\
END{printf("Column1 min: %f\nColumn1 max: %f\nColumn2 min: %f\nColumn2 max:%f\n",min1,max1,min2,max2)}' file.dat
첫 번째 행(조건이 있는 규칙)의 해당 값을 사용하여 두 열의 최소값과 최대값을 초기화 한 NR==1
다음 연속 행을 스캔하여 해당 값이 현재 최대값보다 큰지 확인합니다. 현재 최소값보다 각각(조건이 있는 규칙) NR>1
)
파일 끝에(조건이 있는 규칙 END
) 결과가 인쇄됩니다.
알아채다이는 다음과 같이 가정합니다.빈 줄 없음. 그렇다면 조건을 NR>1
로 바꿔야 합니다 NR>1 && NF>0
. 빈 줄이 있을 수 있는 경우첫 번째 전에, 사용
awk '!init && NF>0 {init=1; min1=max1=$1; min2=max2=$2} \
init==1 && NF>0 {if ($1<min1) {min1=$1} else if ($1>max1) {max1=$1};\
if ($2<min2) {min2=$2} else if ($2>max2) {max2=$2}; }\
END{printf("Column1 min: %f\nColumn1 max: %f\nColumn2 min: %f\nColumn2 max:%f\n",min1,max1,min2,max2)}' file.dat
이는 변수를 사용하여 init
비어 있지 않은 행이 발견되었는지 확인하고 비어 있지 않은 첫 번째 행의 내용을 사용하여 두 열의 현재 최대/최소 값을 미리 설정합니다. 이 통계(비어 있지 않은) 행은 init
설정 시(이 초기화 이후) 항목에만 고려됩니다 .
일반적으로 말하면 파일이 필요하지 않으며 cat
결과를 awk
.
답변3
사용datamash
그리고 printf
:
for f in 1 2 ; do printf 'Column #%s\nmax - %s\nmin - %s\n\n' $f \
$(datamash -W max $f min $f < file.dat); done
...또는 루프가 없습니다.
printf 'Column #%s\nmax - %s\nmin - %s\n\n' \
$(datamash -W max 1 min 1 max 2 min 2 < file.dat |
tr -s '\t' '\n' | paste - - | nl)
산출:
Column #1
max - 0.4916
min - 0
Column #2
max - -23.4334
min - -24.1254
답변4
이것은 열 1에서 작동합니다(평균 최대값과 최소값을 계산합니다).
sort -n -k 1 file |awk '{SUM+=$1 ; if ( NR == 1) MIN=$1} END{print "Average - "SUM/NR, "Min time - "MIN,"Max Time - "$1}'
2열입니다
sort -n -k 2 file |awk '{SUM+=$1 ; if ( NR == 1) MIN=$1} END{print "Average - "SUM/NR, "Min time - "MIN,"Max Time - "$1}'